TCP Chat Client/Server Programming in Unix Using C Programming
🎯 Introduction
TCP (Transmission Control Protocol) chat client/server programming allows communication between multiple clients and a central server over a network using sockets. In this blog post, we will explore a simple implementation of a TCP chat client and server using C programming on Unix-like systems. The code examples provided here will be updated and explained in detail to ensure a better understanding of the concepts involved.
🎯 Concept
The TCP chat application consists of two main components: the chat server and the chat client. The chat server listens for incoming connections from multiple clients and relays messages to the appropriate recipients. The chat client connects to the server and sends messages, while also receiving messages from the server and displaying them to the user.
The communication between the server and clients occurs through sockets, which are endpoints for communication channels. TCP ensures reliable, ordered, and error-checked delivery of data between applications running on different devices.
🎯 Chat Server Detailed Explanation
👉 Chat Server Code
Let's start by understanding the TCP chat server implementation in C:
#include <sys/types.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <string.h>
int main() {
int sfd, cfd;
fd_set rset;
char buff[1024] = " ";
struct sockaddr_in server;
sfd = socket(AF_INET, SOCK_STREAM, 0);
if (sfd < 0) {
printf("Socket creation failed.\n");
return -1;
}
bzero(&server, sizeof(struct sockaddr_in));
server.sin_family = AF_INET;
server.sin_port = htons(1005);
inet_aton("172.16.29.110", &server.sin_addr);
if (bind(sfd, (struct sockaddr*)&server, sizeof(server)) < 0) {
printf("Binding failed.\n");
return -1;
}
listen(sfd, 7);
cfd = accept(sfd, NULL, NULL);
for (;;) {
FD_ZERO(&rset);
FD_SET(0, &rset); // 0 represents the standard input (stdin)
FD_SET(cfd, &rset);
select(cfd + 1, &rset, NULL, NULL, NULL);
if (FD_ISSET(0, &rset)) {
printf("Enter the message:\n");
scanf("%s", buff);
write(cfd, buff, strlen(buff));
}
if (FD_ISSET(cfd, &rset)) {
read(cfd, buff, 1024);
printf("Message received: %s\n", buff);
}
}
close(cfd);
close(sfd);
return 0;
}
👉 Explanation:
We begin by importing the necessary header files and defining some variables required for the server.
We create a socket using socket(AF_INET, SOCK_STREAM, 0). The AF_INET specifies IPv4, and SOCK_STREAM indicates a reliable, two-way, connection-based byte stream (TCP).
The server's address information is set in the server structure, including the IP address and port number to bind to.
We bind the socket to the server address using bind().
The server starts listening for incoming connections using listen(sfd, 7), with a backlog of 7 pending connections.
The server accepts a client connection using accept(sfd, NULL, NULL), and the returned cfd is the file descriptor representing the connected client.
In an infinite loop, we use select() to monitor both stdin (standard input) and the client socket cfd for any incoming data.
If data is available on stdin, the server reads the user's input message, sends it to the client using write(), and continues listening for more input.
If data is available on the client socket cfd, the server reads the incoming message from the client using read() and displays it.
The loop continues until the server is terminated.
Finally, the server closes the client and server sockets using close(cfd) and close(sfd).
🎯 Chat Client Detailed Explanation
👉 Chat Client Code
Now, let's understand the TCP chat client implementation in C:
#include <sys/types.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <string.h>
int main() {
int sfd;
fd_set rset;
char buff[1024] = " ";
struct sockaddr_in server;
sfd = socket(AF_INET, SOCK_STREAM, 0);
if (sfd < 0) {
printf("Socket creation failed.\n");
return -1;
}
bzero(&server, sizeof(struct sockaddr_in));
server.sin_family = AF_INET;
server.sin_port = htons(1005);
inet_aton("172.16.29.110", &server.sin_addr);
printf("Connect: %d\n", connect(sfd, (struct sockaddr*)&server, sizeof(server)));
for (;;) {
FD_ZERO(&rset);
FD_SET(0, &rset); // 0 represents the standard input (stdin)
FD_SET(sfd, &rset);
select(sfd + 1, &rset, NULL, NULL, NULL);
if (FD_ISSET(0, &rset)) {
printf("Enter the message:\n");
scanf("%s", buff);
write(sfd, buff, strlen(buff));
}
if (FD_ISSET(sfd, &rset)) {
read(sfd, buff, 1024);
printf("Message received: %s\n", buff);
}
}
close(sfd);
return 0;
}
👉 Explanation:
Similar to the server, we import the required header files and define variables for the client.
We create a socket using socket(AF_INET, SOCK_STREAM, 0).
The client's address information is set in the server structure, including the IP address and port number to connect to.
We attempt to connect to the server using connect(sfd, (struct sockaddr*)&server, sizeof(server)).
If the connection is successful, the client enters an infinite loop, monitoring both stdin (standard input) and the server socket sfd for any incoming data.
If data is available on stdin, the client reads the user's input message, sends it to the server using write(), and continues listening for more input.
If data is available on the server socket sfd, the client reads the incoming message from the server using read() and displays it.
The loop continues until the client is terminated.
Finally, the client closes the socket using close(sfd).
Sample Output
[root@localhost chat]# ./tcpchatserver
bind=0
Enter the message
kala
message received hema
Enter the message
[root@localhost chat]# ./tcpchatclient
connect=0
message received kala
Enter the message
hema
🎯 Summary
This blog post introduced TCP chat client/server programming in C on Unix-like systems, providing a step-by-step explanation of the code examples. The concept of TCP communication was explained, highlighting its reliability and error-checking capabilities.
The chat server implementation demonstrated socket creation, binding to a specific IP address and port, and listening for incoming connections. Once a client connected, the server relayed messages to and from the client using the select() function to monitor both stdin and the client socket.
On the other hand, the chat client code showed socket creation and connection to the server. It allowed users to send and receive messages from the server using select() to monitor stdin and the server socket.
By understanding the provided examples, developers can build more robust and feature-rich chat applications, such as adding support for multiple clients, handling user identities, or implementing encryption for secure communication.
🎯 Key Points
TCP chat client/server programming involves communication between multiple clients and a central server over a network using sockets.
TCP ensures reliable, ordered, and error-checked data delivery between applications running on different devices.
The server code demonstrated socket creation, binding, listening for connections, and relaying messages between clients.
The client code showed socket creation, connection to the server, and sending/receiving messages.
Developers can enhance the applications by supporting multiple clients, handling user identities, and implementing security measures like encryption.