Network Communication Using Sockets on Linux ===================
- Network Communication with Sockets on Linux
-
- Understanding Sockets
-
- Types of Sockets
-
- Socket Usage Example (SOCK_STREAM)
-
- Parameter Explanation
- 4.1 socket()
- 4.2 bind()
- Byte Order Considerations
- 4.3 listen(), connect()
- 4.4 accept()
- 4.5 read(), write(), and related functions
- 4.6 close()
-
- Understanding Sockets
A socket represents a communication endpoint in computer networks, operating at the TCP/UDP and IP layers.
In Linux systems, sockets are treated as files, allowing operations similar to file I/O for network communication.
- Types of Sockets
Different protocols support distinct socket types:
-
TCP: SOCK_STREAM
-
UDP: SOCK_DGRAM
-
IP: SOCK_RAW (less commonly used)
-
Socket Usage Example (SOCK_STREAM)
Here's a basic example demonstrating a server and client implementation.
Server Implementation
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
const char MESSAGE[] = "Socket Network Programming Test String!\n";
int main(int argc, char *argv[]) {
int server_socket = 0;
int port_number = 0;
int result = 0;
struct sockaddr_in server_address;
if (2 != argc) {
fprintf(stderr, "Usage: %s <port>\n", argv[0]);
exit(1);
}
server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (server_socket == -1) {
fprintf(stderr, "Failed to create socket!\n");
exit(1);
} else {
fprintf(stderr, "Socket created successfully!\n");
}
port_number = atoi(argv[1]);
bzero(&server_address, sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
server_address.sin_port = htons(port_number);
result = bind(server_socket, (struct sockaddr *)&server_address, sizeof(server_address));
if (result == 0) {
fprintf(stderr, "Binding completed!\n");
} else {
fprintf(stderr, "Binding failed!\n");
close(server_socket);
exit(1);
}
result = listen(server_socket, 5);
if (result == -1) {
fprintf(stderr, "Unable to listen on socket!\n");
close(server_socket);
exit(1);
}
while (1) {
struct sockaddr_in client_info = { 0 };
int client_socket = 0;
int client_length = sizeof(client_info);
client_socket = accept(server_socket, (struct sockaddr *)&client_info, &client_length);
if (client_socket == -1) {
fprintf(stderr, "Connection acceptance failed!\n");
close(server_socket);
exit(1);
}
write(client_socket, MESSAGE, strlen(MESSAGE));
close(client_socket);
}
close(server_socket);
return 0;
}
Client Implementation
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
int main(int argc, char *argv[]) {
int client_socket = 0;
int port_number = 0;
int result = 0;
char buffer[256] = "";
struct sockaddr_in server_address;
if (3 != argc) {
fprintf(stderr, "Usage: %s <server> <port>\n", argv[0]);
exit(1);
}
client_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (client_socket == -1) {
fprintf(stderr, "Failed to create socket!\n");
exit(1);
} else {
fprintf(stderr, "Socket created successfully!\n");
}
port_number = atoi(argv[2]);
bzero(&server_address, sizeof(server_address));
server_address.sin_family = AF_INET;
inet_addr(argv[2], &server_address.sin_addr.s_addr);
server_address.sin_port = htons(port_number);
result = connect(client_socket, (struct sockaddr *)&server_address, sizeof(server_address));
if (result == 0) {
fprintf(stderr, "Connection established!\n");
} else {
fprintf(stderr, "Connection failed!\n");
close(client_socket);
exit(1);
}
result = read(client_socket, buffer, sizeof(buffer));
if (result > 0) {
printf("%d: %s", result, buffer);
} else {
fprintf(stderr, "Read status = %d\n", result);
}
close(client_socket);
return 0;
}
- Parameter Details
4.1 socket()
int socket(int domain, int type, int protocol);
This function returns a file descriptor for the socket.
- domain: Address family (e.g., AF_INET for IPv4, AF_INET6 for IPv6).
- type: Socket type (e.g., SOCK_STREAM for TCP, SOCK_DGRAM for UDP).
- protocol: Specific protocol (e.g., IPPROTO_TCP, IPPROTO_UDP). If zero, defaults based on type.
4.2 bind()
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
Binds a socket to a specific address and port.
- sockfd: File descriptor of the socket.
- addr: Pointer to address structure.
- addrlen: Size of the address structure.
Byte Order Considerations
Host byte order refers to how multi-byte data is stored in memory (big-endian vs little-endian). Network byte order uses big-endian representation. When binding addresses, convert host byte order to network byte order using functions like htonl() and htons().
4.3 listen(), connect()
The listen() function makes a socket ready to accept incoming connections. It requires two parameters: the socket file descriptor and the maximum number of queued connections.
The connect() functon establishes a connection to a remote socket. Parameters include the socket file descriptor, the target address, and its length.
4.4 accept()
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
This function waits for an incoming connection and returns a new socket for communication with the client.
- sockfd: Listening socket.
- addr: Client address information.
- adddrlen: Size of client address structure.
Note: accept() blocks until a connection arives. It creates a new socket for each accepted connection.
4.5 read(), write(), and Related Functions
After establishing a connection, data can be transferred using standard I/O functions:
read()/write()recv()/send()recvfrom()/sendto()recvmsg()/sendmsg()
The sendmsg() and recvmsg() functions are recommended as they provide the most flexibility.
4.6 close()
#include <unistd.h>
int close(int fd);
Closes a socket, releasing associated resources. This removes the reference to the socket, and when the reference count reaches zero, the connection terminates gracefully.