Sockets
A socket is an abstract representation of an "endpoint for communication". They can be either:
- Connection based or connectionless.
- Packet based or stream based.
- Reliable or unreliable.
Sockets are characterised by their domain, type, and transport protocol. There are two types of sockets:
- Connection-based sockets communicate client-server: The server waits for a connection from the client.
- Connectionless sockets are peer-to-peer: Each process is symmetric.
Common domains consist of:
- AF_UNIX: Address format is UNIX path-name.
- AF_INET: Address format is host and port number.
Common types consist of:
- Virtual circuit: Received in order transmitted and reliably.
- Datagram: Arbitrary order and unreliable.
Common transport protocols consist of:
- TCP/IP (virtual circuit)
- UDP (datagram)
BSD Socket APIs
socket()
: Creates a socket of a given domain, type, and protocol.bind()
: Assigns a name to the socket.listen()
: Specifies the number of pending connections that can be queued for a server socket.accept()
: Server accepts a connection request from a client.connect()
: Client requests a connection to a server.send(), sendto
: Write to connection.recv(), recvfrom
: Read from connection.shutdown()
: End sending or receiving.close()
: Close a socket and terminate a TCP connection.
Connection-based Sockets
With connection-based sockets, the server performs the following actions:
socket()
bind()
listen()
accept()
send()
recv()
shutdown()
close()
while the client performs the following actions:
socket()
connect()
send()
recv()
shutdown()
close()
Connectionless Sockets
Due to communication being symmetric, all devices perform the following actions:
socket()
bind()
sendto()
recvfrom()
shutdown()
close()
Example
// Server
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
const int NUM_OF_CONNECTIONS = 10;
int main(void) {
struct sockaddr_in server_addr;
struct sockaddr client_addr;
socklen_t client_addr_len;
char buf[1024];
int fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd == -1) {
fprintf(stderr, "[Error] - Failed to create socket.\n");
return 1;
}
server_addr.sin_family = AF_INET;
// Bind socket so it's able to be connected to from anywhere
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
// Bind socket to port 3000
server_addr.sin_port = htons(3000);
if (bind(fd, (struct sockaddr *) &server_addr, sizeof(server_addr)) == -1) {
fprintf(stderr, "[Error] - Failed to bind socket.\n");
return 1;
}
if (listen(fd, NUM_OF_CONNECTIONS) == -1) {
fprintf(stderr, "[Error] - Failed to listen for connections.\n");
return 1;
}
int client_fd = accept(fd, &client_addr, &client_addr_len);
if (client_fd == -1) {
fprintf(stderr, "[Error] - Failed to accept connection.\n");
return 1;
}
// Do something with socket
int bytes_received = recv(client_fd, buf, 1023, 0);
if (bytes_received == -1) {
fprintf(stderr, "[Error] - Failed to receive data.\n");
return 1;
}
buf[bytes_received] = '\0';
printf("Received from client: %s\n", buf);
if (shutdown(client_fd, SHUT_RDWR) == -1) {
fprintf(stderr, "[Error] - Failed to shutdown connection.\n");
return 1;
}
close(client_fd);
close(fd);
return 0;
}
// Client
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
const int NUM_OF_CONNECTIONS = 10;
int main(void) {
struct sockaddr_in server_addr;
struct sockaddr client_addr;
socklen_t client_addr_len;
char buf[1024];
char *message = "Hello, world!\n";
int fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd == -1) {
fprintf(stderr, "[Error] - Failed to create socket.\n");
return 1;
}
server_addr.sin_family = AF_INET;
if (inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr) != 1) {
fprintf(stderr, "[Error] - Failed to convert presentation format address to network format.\n");
return 1;
}
server_addr.sin_port = htons(3000);
if (connect(fd, (struct sockaddr *) &server_add, sizeof(server_addr)) == -1) {
fprintf(stderr, "[Error] - Failed to connect to server.\n");
return 1;
}
send(fd, message, strlen(message), 0);
if (shutdown(client_fd, SHUT_RDWR) == -1) {
fprintf(stderr, "[Error] - Failed to shutdown connection.\n");
return 1;
}
close(fd);
return 0;
}