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