#include <sys/types.h> #include <sys/socket.h> int socket(int domain, int type, int protocol)Returns a file descriptor (called a socket ID) if successful, -1 otherwise.
The type arguments are
Note that the socket returns a socket descriptor which is the same as a file descriptor (-1 if failure).
#include <sys/types.h> #include <sys/socket.h> int bind(int sid, struct sockaddr *addrPtr, int len)Where
struct sockaddr_in { short sin_family; // = AF_INET u_short sin_port; // is a port number struct in_addr sin_addr; // an IP address }For unix sockets (only works between processes on the same machine)
struct sockaddr { short sin_family; // = AF_UNIX char sin_port[]; // is a port number }
#include <sys/types.h> #include <sys/socket.h> int listen(int sid, int size)Where size it the number of pending connection requests allowed (typically limited by Unix kernels to 5).
#include <sys/types.h> #include <sys/socket.h> int accept(int sid, struct sockaddr *addrPtr, int *lenPtr)Returns the address of client connecting to socket
if lenPtr or addrPtr equal zero, no address structure is returned
lenPtr is the maximum size of address structure that can be called, returns the actual value.
#include <sys/types.h> #include <sys/socket.h> int send(int sid, const char *bufferPtr, int len, int flags)flag is either
#include <sys/types.h> #include <sys/socket.h> int recv(int sid, char *bufferPtr, int len, int flags)flags can be either
#include <sys/types.h> #include <sys/socket.h> int shutdown(int sid, int how)Disables sending (how=1 or how=2) or receiving (how=0 or how=2).
#include <sys/types.h> #include <sys/socket.h> int connect(int sid, struct sockaddr *addrPtr, int len)
#include <sys/types.h> #include <sys/socket.h> int sendto(int sid, const char *bufferPtr, int len, int flag, struct sockaddr *addrPtr, int len)
#include <sys/types.h> #include <sys/socket.h> int recvfrom(int sid, const char *bufferPtr, int len, int flag, struct sockaddr *addrPtr, int *lenPtr)
#include <netdb.h> struct hostent *gethostbyname(const char *hostname)Translates a DNS name into a hostent.
The hostent stucture is as follows:
struct hostent { char *h_name; // official (canonical) name of the host char **h_aliases; // null terminated array of alternative hostnames int h_addrtype; // host address type AF_INET or AF_INET6 int h_length; // 4 or 16 bytes char **h_addr_list;// IPv4 or IPv6 list of addresses }Error is return through h_error which can be:
#include <unistd.h> int gethostname(char *hostname, size_t nameLength)Returns -1 on failure, 0 on success.
MAXHOSTNAMELEN is defined in <sys/param.h>.
uint_16t htons(uint_16t v);
uint_32t htonl(uint_32t v);
uint_16t ntohs(uint_16t v);
uint_32t ntohl(uint_32t v);
#include <arpa/inet.h> int inet_pton(int family, const char *strPtr, void *addrPtr);returns 1 if OK, 0 if presentation error, -1 error
Where family is either AF_INET or AF_INET6.
The strPtr is the ip address as a dotted string.
Finally, addrPtr points to either the 32 bit result (AF_INET) or 128 bit result (AF_INET6).
#include <arpa/inet.h> int inet_ntop(int family, const char *addrPtr, char *strPtr, size_t len);returns 1 if OK, 0 if presentation error, -1 error
Where family is either AF_INET or AF_INET6.
The strPtr is the return ip address as a dotted string.
Finally, addrPtr points to either the 32 bit (AF_INET) or 128 bit (AF_INET6).
Length is the size of destination.
int listenFd, connectFd; struct sockaddr_in serverAddr; listenFd = socket(AF_INET, SOCK_STREAM, 0); // get a tcp/ip socket bzero(&serverAddr, sizeof(serverAddr)); serverAddr.sin_family = AF_INET; serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); // any iternet interface // on this server. serverAddr.sin_port = htons(13); bind(listenFd, (struct sockaddr_in *) &serverAddr, sizeof(serverAddr)); listen(listenFd, 5); for ( ; ; ) { connectFd = accept(listenFd, (struct sockaddr_in *) NULL, NULL); // .. read and write operations on connectFd .. shutdown(connectFd, 2); close(connectFd); }Note that the above is an iterative server, which means that it serves one connection at a time.
To build a concurrent server, a fork is performed after the accept. The child process closes listenFd, and communicates using connectFd. The parent process closses connectFd, and then loops back to the accept to wait for another connection request.
int sockFd; struct sockaddr_in serverAddr; sockFd = socket(AF_INET, SOCK_STREAM, 0); // get a tcp/ip socket bzero(&serverAddr, sizeof(serverAddr)); serverAddr.sin_family = AF_INET; inet_pton(AF_INET, serverName, serverAddr.sin_addr); // host IP # serverAddr.sin_port = htons(13); connect(sockFd, (struct sockaddr_in *) serverAddr, sizeof(serverAddr)); // .. read and write operations on sockFd .. shutdown(sockFd, 2); close(sockFd);