This section presents a simple echo server-client program using TCP. The program is denoted by C13.2. For simplicity, we assume that both the server and client run on the same computer, and the server port number is hard coded as 1234. The following chart shows the algorithms and sequence of actions of the TCP server and client.
/******** C13.2.a: TCP server.c file ********/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netdb.h>
#define MAX 256
#define SERVER_HOST “localhost”
#define SERVER_IP “127.0.0.1”
#define SERVER_PORT 1234
struct sockaddr_in server_addr, client_addr;
int mysock, csock; // socket descriptors
int r, len, n; // help variables
int server_init()
{
printf(“================== server init ======================\n”);
// create a TCP socket by socket() syscall
printf(“1 : create a TCP STREAM socket\n”);
mysock = socket(AF_INET, SOCK_STREAM, 0);
if (mysock < 0){
printf(“socket call failed\n”); exit(1);
}
printf(“2 : fill server_addr with host IP and PORT# info\n”);
// initialize the server_addr structure
server_addr.sin_family = AF_INET; // for TCP/IP
server_addr.sin_addr.s_addr = htonl(INADDR_ANY); // This HOST IP
server_addr.sin_port = htons(SERVER_PORT); // port number 1234
printf(“3 : bind socket to server address\n”);
r = bind(mysock,(struct sockaddr*)&server_addr,sizeof(server_addr));
if (r < 0){
printf(“bind failed\n”); exit(3);
}
printf(” hostname = %s port = %d\n”, SERVER_HOST, SERVER_PORT);
printf(“4 : server is listening ….\n”);
listen(mysock, 5); // queue length = 5
printf(“=================== init done =======================\n”);
}
int main()
{
char line[MAX]; server_init();
while(1){ // Try to accept a client request
printf(“server: accepting new connection ….\n”);
// Try to accept a client connection as descriptor newsock
len = sizeof(client_addr);
csock = accept(mysock, (struct sockaddr *)&client_addr, &len);
if (csock < 0){
printf(“server: accept error\n”); exit(1);
}
printf(“server: accepted a client connection from\n”);
printf(“——————————————– \n”);
printf(“Clinet: IP=%s port=%d\n”,
inet_ntoa(client_addr.sin_addr.s_addr),
ntohs(client_addr.sin_port));
printf(“——————————————– \n”);
// Processing loop: client_sock <== data ==> client
while(1){
n = read(csock, line, MAX);
if (n==0){
printf(“server: client died, server loops\n”);
close(csock);
break;
}
// show the line string
printf(“server: read n=%d bytes; line=%s\n”, n, line);
// echo line to client
n = write(csock, line, MAX);
printf(“server: wrote n=%d bytes; ECHO=%s\n”, n, line);
printf(“server: ready for next request\n”);
}
}
}
/******** C13.2.b: TCP client.c file TCP ********/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netdb.h>
#define MAX 256
#define SERVER_HOST “localhost”
#define SERVER_PORT 1234 struct sockaddr_in server_addr;
int sock, r;
int client_init()
{
printf(“======= clinet init ==========\n”);
printf(“1 : create a TCP socket\n”);
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock<0){
printf(“socket call failed\n”); exit(1);
}
printf(“2 : fill server_addr with server’s IP and PORT#\n”);
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY); // localhost
server_addr.sin_port = htons(SERVER_PORT); // server port number
printf(“3 : connecting to server ….\n”);
r = connect(sock,(struct sockaddr*)&server_addr, sizeof(server_addr));
if (r < 0){
printf(“connect failed\n”); exit(3);
}
printf(“4 : connected OK to\n”);
printf(“—————————————————– \n”);
printf(“Server hostname=%s PORT=%d\n”, SERVER_HOST, SERVER_PORT);
printf(“—————————————————– \n”);
printf(“========= init done ==========\n”);
}
int main()
{
int n;
char line[MAX], ans[MAX];
client_init();
printf(“******** processing loop *********\n”);
while (1){
printf(“input a line : “);
bzero(line, MAX); // zero out line[ ]
fgets(line, MAX, stdin); // get a line from stdin
line[strlen(line)-1] = 0; // kill \n at end
if (line[0]==0) // exit if NULL line
exit(0);
// Send line to server
n = write(sock, line, MAX);
printf(“client: wrote n=%d bytes; line=%s\n”, n, line);
// Read a line from sock and show it
n = read(sock, ans, MAX);
printf(“client: read n=%d bytes; echo=%s\n”, n, ans);
}
}
Figure 13.8 shows the sample outputs of running the TCP server-client program C13.2.
Source: Wang K.C. (2018), Systems Programming in Unix/Linux, Springer; 1st ed. 2018 edition.