Implementing a Single-Threaded Blocking Bare Bones TCP/IP Server
In this article, we will explore the implementation of a simple, single-threaded, blocking TCP/IP server using C programming language. The server will listen for incoming connections and send a greeting message to the client. We will use the BSD socket library to create a socket and handle the communication with the client.
Understanding the Basics
Before diving into the implementation, let’s understand the basics of TCP/IP sockets. A TCP/IP socket is a endpoint for communication between two devices (computer or router) that is used to send and receive data over the internet. The socket is created by using the `socket()` function provided by the BSD socket library.
The `socket()` function creates a socket, which is a file descriptor that can be used to perform operations on the socket such as binding, listening, and accepting connections. A socket can be created in two main types: stream socket and datagram socket. Stream socket is used for reliable, connection-oriented communication, where the data is sent in a stream and the sender cannot guarantee that the data is delivered in the same order. On the other hand, datagram socket is used for best-effort, connectionless communication, where the data is sent in discrete packets, and the sender does not guarantee that the data is delivered.
Implementing the Server
The server code is implemented using the following steps:
1. Create a socket using the `socket()` function.
2. Bind the socket to a specific IP address and port using the `bind()` function.
3. Listen for incoming connections using the `listen()` function.
4. Accept incoming connections using the `accept()` function.
5. Read data from the client and send a response back.
Here is the code implementation:
“`c
include
include
include
include
include
include
define PORT 8080
int main() {
int sockfd, connfd;
struct sockaddr_in server_addr, client_addr;
socklen_t client_len = sizeof(client_addr);
char buffer[256];
// Create a socket
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror(“socket creation failed”);
exit(1);
}
// Set the address and port number of the server
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(PORT);
// Bind the socket to the specified IP address and port
if (bind(sockfd, (struct sockaddr )&server_addr, sizeof(server_addr)) < 0) {
perror(“bind failed”);
exit(1);
}
// Listen for incoming connections
if (listen(sockfd, 3) < 0) {
perror(“listen failed”);
exit(1);
}
printf(“Server listening…\n”);
while (1) {
// Accept an incoming connection
connfd = accept(sockfd, (struct sockaddr )&client_addr, &client_len);
if (connfd < 0) {
perror(“accept failed”);
continue;
}
printf(“Connected to client IP address: %s, port: %d\n”,
inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
// Read data from the client
recv(connfd, buffer, 256, 0);
printf(“Received data from client: %s\n”, buffer);
// Send a response back to the client
char response = “Hello, client!”;
send(connfd, response, strlen(response), 0);
}
close(sockfd);
return 0;
}
“`
RUNNING THE SERVER
To run the server, you can use the following command:
“`bash
gcc server.c -o server
./server
“`
This will start the server listening for incoming connections on port 8080. When a client connects to the server, the server will read the data sent by the client, print it to the console, and send a response back to the client.
Conclusion
In this article, we have implemented a simple, single-threaded, blocking TCP/IP server using C programming language. The server creates a socket, binds it to a specific IP address and port, listens for incoming connections, and accepts incoming connections to handle communication with the client. This implementation provides a basic understanding of how to create a TCP/IP server using C programming language.