socket

see: https://beej.us/guide/bgnet/html/split/

see: https://www.gnu.org/software/libc/manual/html_node/Sockets.html

socket()

creates socket (without setting its IP address or port)

sockets are endpoints / communication channels for different processes (if local, then the same host on both sides) which are handled as files.

int sockfd = socket(AF_INET, SOCK_STREAM, 0); // we don't use anything else in this course

endpoint = IP + port number

address families:

IPv4 → AF_INET

IPv6 → AF_INET

Unix Domain Sockets (local) → AF_UNIX

socket types:

TCP → SOCK_STREAM

UDP → SOCK_DGRAM

protocols:

0 → default protocol for socket type

setsockopt()

set socket options as server

useful to avoid the “address already in use error” EADDRINUSE - which forces you to wait one minute after terminating the server for the socket to terminate aswell

int optval = 1;
setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval);

bind()

assigns address to socket as server

struct sockaddr_in *sa;
bind(sockfd, sa, sizeof(struct sockaddr_in);

listen()

marks socket as passive for servers (for TCP only)

listen(sockfd, queueLen);

accept()

blocks until there is a connection as server

int connfd = accept(sockfd, NULL, NULL);

other arguments: pointer to client address and its size

connect()

connects choosing a random open port as client

struct sockaddr_in server_addr;
connect(sockfd, &server_addr, sizeof(server_addr);

getaddrinfo()

creates an address (replaces the deprecated gethostbyname which doesn’t support IPV6).

errors can be translated to human readable message with gai_strerror .

internal linked list in struct can be freed with freeaddrinfo .

struct addrinfo hints, *ai;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;

int res = getaddrinfo("localhost"/NULL, "1280", &hints, &ai);
if (res != 0) {
	// error
}

int sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (sockfd == -1) {
	// error
}
if (connect/bind(sockfd, ai->ai_addr, ai->ai_addrlen) == -1) {
	// error
}
freeaddrinfo(ai);

read() / write()

htonl() / ntohl()

you can use any function to write via the socket as long as it doesn’t use a buffer.

specialized functions for sockets: send() , recv()

keep in mind that the byte order is different on a network

ntohl(): network byte order → host byte order (x86 is little endian but not all architectures)

htonl(): host byte order → network byte order (big endian)

int i = 0x12345678;

// Little endian:      0x78 0x56 0x34 0x12 <- each block is one byte
// Big endian:         0x12 0x34 0x56 0x78