-
Notifications
You must be signed in to change notification settings - Fork 1
How Sockets Work
Sockets are the "endpoints" of a 2 way communication channel. We'll be using sockets to handle network communications between the client (e.g., a web browser) and our server. For webserv we will use: TCP (Transmission Control Protocol) sockets, which provide a reliable, more secure way to communicate, ensuring data is sent successfully.
- Create a Socket: Use the
socket()function to create a socket. - Bind the Socket (Server-Side): Use the
bind()function to bind the socket to an address and port. - Listen on the Socket (Server-Side): Use the
listen()function to listen for incoming connections. - Accept Connections (Server-Side): Use the
accept()function to accept incoming connections. This is where we would usepoll()I think. - Connect to a Server (Client-Side): Use the
connect()function to connect to a server. (NOTE: NOT SURE HOW TO SET THIS ONE UP, OR IF WE EVEN NEED TO??) - Send/Receive Data: Use
send()/recv()orwrite()/read()to send and receive data. - Close the Socket: Use the
close()function to close the socket when done.
Creates a new socket
int socket(int domain, int type, int protocol);-
domain: Specifies the communication domain,AF_INETfor IPv4,AF_INET6for IPv6. -
type: Specifies the communication semantics,SOCK_STREAMforTCPandSOCK_DGRAMforUDP -
protocol: Specifies the protocol to be used with the socket. Not entirely sure how this works, but normally only a single protocol exists to support a particular socket, so we can just set this as0i think.
Read more here: https://man7.org/linux/man-pages/man2/socket.2.html
Example:
int sockfd = socket(AF_INET, SOCK_STREAM, 0); // returns the socket "file descriptor"Binds a socket to an address/port
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);-
sockfd: File descriptor of the socket to be bound. -
addr: A pointer to asockaddr(see below) structure representing the address to bind to -
addrlen: The size of the address structure
Read more here: https://man7.org/linux/man-pages/man2/bind.2.html
What is the sockaddr data structure??
The sockaddr structure is a generic descriptor for any type of socket operation in C/C++. It's used to specify socket addresses in network functions, such as bind(), connect(), accept(). However, ITS A GENERIC STRUCTURE!! We would use sockaddr_in for IPv4 and sockaddr_in6 for IPv6. These include additional fields for their address family. These specific structures can be cast to sockaddr when used with socket functions.
// System definition
struct sockaddr {
sa_family_t sa_family;
char sa_data[14];
}
// For IPv4
struct sockaddr_in {
short sin_family; // Address family (AF_INET for IPv4)
unsigned short sin_port; // Port number in Network Byte Order
struct in_addr sin_addr; // Internet address
char sin_zero[8]; // Padding to make structure the same size as sockaddr
};-
sin_family: Corresponds tosa_familyinsockaddr. Always set toAF_INETfor IPv4 addresses. -
sin_port: This is the port number (in network byte order) associated with the socket. We would usehton()which ensures the port number given from config file is in the correct "byte order". No idea what this means I'll be honest, but we would do something like:hton(8080)for example -
sin_addr: Dont fully understand what this does, but its the IP address for the socket, I'm not sure if we would have to set this.
Example:
struct sockaddr_in address;
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY; // bind to any address
address.sin_port = htons(8080); // port number
bind(sockfd, (struct sockaddr *)&address, sizeof(address));Marks the socket referred to by sockfd as a passive socket; that is, as a socket that will be used to accept incoming connection requests using accept()
int listen(int sockfd, int backlog);-
sockfd: The file descriptor of the socket -
backlogThe max length of the queue of pending connections. Basically its the number of connections that can be waiting while the process is handling a particular connection. Not sure what we sent this to??
Read more here: https://man7.org/linux/man-pages/man2/listen.2.html
Accepts a connection on a socket
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);-
sockfd: The file descriptor of the LISTENING socket. -
addr: A pointer to asockaddrstructure. Again - we would usesockaddr_infor IPv4 etc. -
addrlen: On input, this specifies the amount of space pointed to by addr. On output, it specifies the actual length (in bytes) of the address returned.
Read more here: https://man7.org/linux/man-pages/man2/listen.2.html
Example:
struct sockaddr_in client_address;
socklen_t client_addrlen = sizeof(client_address);
int new_socket = accept(sockfd, (struct sockaddr *)&client_address, &client_addrlen);Initiates a connection on a socket
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);-
sockfd: The file descriptor of the socket. -
addr: A pointer to a sockaddr structure specifying the address to connect to. -
addrlen: The size of the address structure.
Example:
int sockfd = socket(AF_INET, SOCK_STREAM, 0); // Create a TCP socket
struct sockaddr_in serv_addr;
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(80); // HTTP port
// Convert IP address to numerical form so that socket can use it
inet_pton(AF_INET, "93.184.216.34", &serv_addr.sin_addr); // example.com IP
if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
// Error handling
perror("Connection failed");
return 1;
}
// Connection is established; can now send/receive data
close(sockfd); // Close the socket when doneUsed to send and receive data. send() and recv() are used with TCP sockets (SOCK_STREAM), and write() and read() can be used interchangeably.
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
ssize_t write(int fd, const void *buf, size_t count);
ssize_t read(int fd, void *buf, size_t count);-
sockfd/fd: The file descriptor of the socket. -
buf: The buffer to send data from or receive data into. -
len/count: The length of the buffer. -
flags: A set of flags that modify the behavior of the send/recv operations.
Example:
char message[] = "Hello, world!";
send(sockfd, message, sizeof(message), 0);
char buffer[1024];
recv(sockfd, buffer, 1024, 0);