Address Information
Overview
Typically C network code begins with address resolution.
Each addrinfo struct, one or more of which is returned by getaddrinfo, contains an Internet address that can be specified in a call to bind or connect. It contains the following fields:
struct addrinfo {
int ai_flags;
int ai_family;
int ai_socktype;
int ai_protocol;
socklen_t ai_addrlen;
struct sockaddr *ai_addr;
char *ai_canonname;
struct addrinfo *ai_next;
};
For Internet-facing code:
- The
ai_familyfield indicates which address family is being used. - The
ai_socktypefield indicates which socket type is being used. - The
ai_addrfield contains data related to the actual address.- Tthis value can be cast to a
struct sockaddr_inorstruct sockaddr_in6, depending on the value of theai_family. - This also specifies a 16-bit port number used to distinguish per-application traffic on the same host.
- Tthis value can be cast to a
API
Socket
The socket function is used to get a socket descriptor. Typically this function is supplied values from a struct addrinfo populated by the getaddrinfo function.
int socket(int domain, int type, int protocol);
Bind
The bind function is used to associate a socket descriptor to a given port on the host machine.
int bind(int sockfd, struct sockaddr *my_addr, int addrlen);
The AI_PASSIVE constant can be passed to a struct addrinfo instance beforehand to indicate on what addresses a socket can accept on. This resolves to either one of the following:
INADDR_ANY. Usually corresponds to address0.0.0.0.IN6ADDR_ANY_INIT. Usually corresponds to address::.INADDR_LOOPBACK. Usually corresponds to address127.0.0.1.IN6ADDR_LOOPBACK_INIT. Usually corresponds to address::1.
Connect
The connect function is used to connect to some host interface listening for incoming connections.
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);
Listen
The listen function is used to prepare a socket for incoming connections.
int listen(int sockfd, int backlog);
Accept
The accept function returns a new socket file descriptor for any pending connection found.
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
Close
The close syscall can be used on socket to close the underlying connection.
For more control, the shutdown function can be used instead. This allows cutting communication off only in one direction. Note this function doesn't close the file descriptor though - close still needs to be called.
int shutdown(int sockfd, int how);
Send/Recv
To send and receive data on a connection-oriented socket, send and recv are used respectively.
int send(int sockfd, const void *msg, int len, int flags);
int recv(int sockfd, void *buf, int len, int flags);
To send and receive data on a connectionless socket, sendto and recvfrom are used respectively.
int sendto(int sockfd, const void *msg,
int len, unsigned int flags,
const struct sockaddr *to, socklen_t tolen);
int recvfrom(int sockfd, void *buf,
int len, unsigned int flags,
struct sockaddr *from, int *fromlen);)