Network UDP TCP Sockets

A few illustrated reminds about UDP TCP sockets.
For complete explanations, please have a look at : https://web.enib.fr/~harrouet


Every following examples can be downloaded here :

code.zip

just write ‘make’ in a terminal to compile all of them.


IP address

#include "main.h"

//======================================================================
void showIpAddress(const char *hostName)
{
	struct hostent *host=gethostbyname(hostName);
	
	if(host)
	  {
			struct in_addr ipAddress=*((struct in_addr *)(host->h_addr));
			printf("`%s' --> %s\n",hostName,inet_ntoa(ipAddress));
	  }
	else
	  {
			printf("unknown host `%s'\n",hostName);
	  }
}

//======================================================================
//						MAIN
//======================================================================
int main(int argc, char **argv)
{
	char hostName[0x100];
	
	gethostname(hostName,0x100);
	
	showIpAddress(hostName);
	
	for(int i=1;i<argc;++i)
	  {
		showIpAddress(argv[i]);
	  }
	return 0;
}
//^^^^^^^^^^^^^^^^^^^^^^^^^^ EOF ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

$ ./prog01_ip_address www.google.fr www.enib.fr
`kerhoas-HP' --> 127.0.1.1
`www.google.fr' --> 216.58.213.131
`www.enib.fr' --> 195.221.233.6

UDP text

Considering we have a Linux PC + another Linux PC or Rasperry PI :

udp_txt.svg

If you want to test with one PC ( with local adress 127.0.0.1) , consider this drawing :

udp_txt_local_address.svg

# CLIENT SIDE : PC

$ ./prog02_udp_send_txt 192.168.0.2 2000
12345
abcdef
# SERVER SIDE : RPI

$ ./prog02_udp_recv_txt 2000
from 192.168.0.2:48748 : 12345

from 192.168.0.2:48748 : abcdef
prog03_udp_txt
#include "main.h"

// $ ./prog02_udp_send_txt 127.0.0.1 2000
// hello
//======================================================================
//						MAIN
//======================================================================
int main(int argc, char **argv)
{	
	int ok;
	int portNumber;
	char msg[0x100];
	struct sockaddr_in toAddr;
	
	//---- check command line arguments ----
	if(argc!=3) { fprintf(stderr,"usage: %s destination port\n",argv[0]); exit(1); }

	//---- extract destination IP address ----
	struct hostent *host=gethostbyname(argv[1]);
								if(!host) { fprintf(stderr,"unknown host %s\n",argv[1]); exit(1); }
	
	in_addr_t ipAddress=*((in_addr_t *)(host->h_addr));

	//---- extract destination port number ----
	if(sscanf(argv[2],"%d",&portNumber)!=1)
								{ fprintf(stderr,"invalid port %s\n",argv[2]); exit(1); }

	//---- create UDP socket ----
	int udpSocket=socket(PF_INET,SOCK_DGRAM,0);
								if(udpSocket==-1) { perror("socket"); exit(1); }
	// ... allowing broadcast (optional)
	int on=1;
	ok = setsockopt(udpSocket,SOL_SOCKET,SO_BROADCAST,&on,sizeof(int));
								if( ok == -1) { perror("setsockopt"); exit(1); }

	for(;;)
	  {
		  //---- read next line on standard input ----
		  if(!fgets(msg,0x100,stdin)) { break; } // [Control]+[d] --> EOF

		  //---- send message to the specified destination/port ----
		  toAddr.sin_family=AF_INET;
		  toAddr.sin_port=htons(portNumber);
		  toAddr.sin_addr.s_addr=ipAddress;
		  ok = sendto(udpSocket,msg,strlen(msg),0,(struct sockaddr *)&toAddr,sizeof(toAddr));
								if( ok == -1){ perror("sendto"); exit(1); }				
	  }

	close(udpSocket);
	
return 0;
}
//^^^^^^^^^^^^^^^^^^^^^^^^^^ EOF ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

#include "main.h"
//======================================================================
//						MAIN
//======================================================================
int main(int argc, char **argv)
{
	int portNumber;
	struct sockaddr_in myAddr;
	char msg[0x100];
	struct sockaddr_in fromAddr;
	int ok;
	
	//---- check command line arguments ----
	if(argc!=2)
									{ fprintf(stderr,"usage: %s port\n",argv[0]); exit(1); }

	//---- extract local port number ----
	if(sscanf(argv[1],"%d",&portNumber)!=1)
									{ fprintf(stderr,"invalid port %s\n",argv[1]); exit(1); }

	//---- create UDP socket ----
	int udpSocket=socket(PF_INET,SOCK_DGRAM,0);
	if(udpSocket==-1)
									{ perror("socket"); exit(1); }
	// ... bound to any local address on the specified port
	myAddr.sin_family=AF_INET;
	myAddr.sin_port=htons(portNumber);
	myAddr.sin_addr.s_addr=htonl(INADDR_ANY);
	ok = bind(udpSocket,(struct sockaddr *)&myAddr,sizeof(myAddr));
									if (ok== -1){ perror("bind"); exit(1); }
	// ... allowing broadcast (optional)
	int on=1;
	ok = setsockopt(udpSocket,SOL_SOCKET,SO_BROADCAST,&on,sizeof(int));
									if (ok== -1){ perror("setsockopt"); exit(1); }

	for(;;)
	  {
		  //---- receive message ----
		  socklen_t len=sizeof(fromAddr);
		  int r=recvfrom(udpSocket,msg,0x100,0,(struct sockaddr *)&fromAddr,&len);
		  if(r==-1)
										{ perror("recvfrom"); exit(1); }

		  //---- display message and source address/port ----
		  msg[r]='\0';
		  printf("from %s:%d : %s\n", inet_ntoa(fromAddr.sin_addr),ntohs(fromAddr.sin_port),msg);
	  }

	close(udpSocket);
return 0;
}
//^^^^^^^^^^^^^^^^^^^^^^^^^^ EOF ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


UDP bin

Datas are not necessarly characters ; sending binary datas supposes knowing byte order.
That’s the purpose of htonl and ntohs functions.

$ ./prog03_udp_send_bin 192.168.0.2 2000
45
789
-78
abcd
78
$ ./prog03_udp_recv_bin 2000
from 192.168.0.2:49963 : 45
from 192.168.0.2:49963 : 789
from 192.168.0.2:49963 : -78
from 192.168.0.2:49963 : 78
prog03_udp_bin
#include "main.h"

// $ ./prog02_udp_send_txt 127.0.0.1 2000
// hello
//======================================================================
//						MAIN
//======================================================================
int main(int argc, char **argv)
{	
	int ok;
	int portNumber;
	int32_t value;
	char msg[0x100];
	struct sockaddr_in toAddr;
	
	//---- check command line arguments ----
	if(argc!=3) { fprintf(stderr,"usage: %s destination port\n",argv[0]); exit(1); }

	//---- extract destination IP address ----
	struct hostent *host=gethostbyname(argv[1]);
								if(!host) { fprintf(stderr,"unknown host %s\n",argv[1]); exit(1); }
	
	in_addr_t ipAddress=*((in_addr_t *)(host->h_addr));

	//---- extract destination port number ----
	if(sscanf(argv[2],"%d",&portNumber)!=1)
								{ fprintf(stderr,"invalid port %s\n",argv[2]); exit(1); }

	//---- create UDP socket ----
	int udpSocket=socket(PF_INET,SOCK_DGRAM,0);
								if(udpSocket==-1) { perror("socket"); exit(1); }
	// ... allowing broadcast (optional)
	int on=1;
	ok = setsockopt(udpSocket,SOL_SOCKET,SO_BROADCAST,&on,sizeof(int));
								if( ok == -1) { perror("setsockopt"); exit(1); }

	for(;;)
	  {
		  //---- read next line on standard input ----
		  if(!fgets(msg,0x100,stdin)) { break; } // [Control]+[d] --> EOF
		  
		    //---- extract 32-bit integer ----
		  if(sscanf(msg,"%d",&value)!=1) continue;

		  //---- convert to network format 32-bit integer ----
		  value=htonl(value);

		  //---- send message to the specified destination/port ----
		  toAddr.sin_family=AF_INET;
		  toAddr.sin_port=htons(portNumber);
		  toAddr.sin_addr.s_addr=ipAddress;
		  ok = sendto(udpSocket,&value,4,0,(struct sockaddr *)&toAddr,sizeof(toAddr)); 
								if( ok == -1){ perror("sendto"); exit(1); }
	  }

	close(udpSocket);
	
return 0;
}
//^^^^^^^^^^^^^^^^^^^^^^^^^^ EOF ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

#include "main.h"
//======================================================================
//						MAIN
//======================================================================
int main(int argc, char **argv)
{
	int ok;
	int portNumber;
	struct sockaddr_in myAddr;
	struct sockaddr_in fromAddr;
	int32_t value;
	
	//---- check command line arguments ----
	if(argc!=2) { fprintf(stderr,"usage: %s port\n",argv[0]); exit(1); }
	  
	//---- extract local port number ----
	if(sscanf(argv[1],"%d",&portNumber)!=1){ fprintf(stderr,"invalid port %s\n",argv[1]); exit(1); }
		
	//---- create UDP socket ----
	int udpSocket=socket(PF_INET,SOCK_DGRAM,0);	// SOCK_DGRAM == UDP
									if( udpSocket==-1 ) { perror("socket"); exit(1); }
	
	// ... bound to any local address on the specified port
	myAddr.sin_family=AF_INET;
	myAddr.sin_port=htons(portNumber);
	myAddr.sin_addr.s_addr=htonl(INADDR_ANY);
	
	ok = bind(udpSocket,(struct sockaddr *)&myAddr,sizeof(myAddr));
									if( ok == -1) { perror("bind"); exit(1); }
	
	// ... allowing broadcast (optional)
	int on=1;
	ok = setsockopt(udpSocket,SOL_SOCKET,SO_BROADCAST,&on,sizeof(int));
									if( ok == -1) { perror("setsockopt"); exit(1); }	

	for(;;)
	  {
			  //---- receive message ----
			  socklen_t len=sizeof(fromAddr);
			   int r=recvfrom(udpSocket,&value,4,0,(struct sockaddr *)&fromAddr,&len);
											if(r==-1){ perror("recvfrom"); exit(1); }
											
			  //---- convert to host format 32-bit integer ----
			  if(r<4)
				{ fprintf(stderr,"4 bytes expected\n"); exit(1); }
			  value=ntohl(value);

			  //---- display value and source address/port ----
			  printf("from %s:%d : %d\n", inet_ntoa(fromAddr.sin_addr),ntohs(fromAddr.sin_port),value);
	  }

	close(udpSocket);
}
//^^^^^^^^^^^^^^^^^^^^^^^^^^ EOF ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


UDP Select server

Since the receive function is blocking, the SELECT function permits switching between several incoming sources.

udp_select.svg

# APP TXT CLIENT : PC

$ ./prog02_udp_send_txt 192.168.0.2 2000
abcd
789

  

# APP BIN CLIENT : PC

$ ./prog03_udp_send_bin 192.168.0.2 2001
45
-78
-4.56
# SERVER SIDE : RPI

$ ./prog04_select 2000 2001
text message from 192.168.0.2:40173 : abcd
binary value from 192.168.0.2:53143 : 45
text message from 192.168.0.2:40173 : 789
binary value from 192.168.0.2:53143 : -78
binary value from 192.168.0.2:53143 : -4
I write on the rpi
prog04_select.c
#include "main.h"
//======================================================================
//						MAIN
//======================================================================
int main(int argc,  char **argv)
{
	int txtPortNumber,binPortNumber;
	struct sockaddr_in myAddr;
	fd_set rdSet;
	char msg[0x100];
	struct sockaddr_in fromAddr;
	int32_t value;
	
	//---- check command line arguments ----
	if(argc!=3)
									{ fprintf(stderr,"usage: %s txt_port bin_port\n",argv[0]); exit(1); }

	//---- extract local port numbers ----
	if(sscanf(argv[1],"%d",&txtPortNumber)!=1)
									{ fprintf(stderr,"invalid port %s\n",argv[1]); exit(1); }
	if(sscanf(argv[2],"%d",&binPortNumber)!=1)
									{ fprintf(stderr,"invalid port %s\n",argv[1]); exit(1); }

	//---- create UDP socket (text) ----
	int txtUdpSocket=socket(PF_INET,SOCK_DGRAM,0);
	if(txtUdpSocket==-1)
									{ perror("socket"); exit(1); }
	  
	// ... bound to any local address on the specified port

	myAddr.sin_family=AF_INET;
	myAddr.sin_port=htons(txtPortNumber);
	myAddr.sin_addr.s_addr=htonl(INADDR_ANY);
	if(bind(txtUdpSocket,(struct sockaddr *)&myAddr,sizeof(myAddr))==-1)
									{ perror("bind"); exit(1); }
	
	// ... allowing broadcast (optional)
	int on=1;
	if(setsockopt(txtUdpSocket,SOL_SOCKET,SO_BROADCAST,&on,sizeof(int))==-1)
									{ perror("setsockopt"); exit(1); }

	//---- create UDP socket (binary) ----
	int binUdpSocket=socket(PF_INET,SOCK_DGRAM,0);
	if(binUdpSocket==-1)
									{ perror("socket"); exit(1); }
									
	// ... bound to any local address on the specified port
	myAddr.sin_family=AF_INET;
	myAddr.sin_port=htons(binPortNumber);
	myAddr.sin_addr.s_addr=htonl(INADDR_ANY);
	if(bind(binUdpSocket,(struct sockaddr *)&myAddr,sizeof(myAddr))==-1)
									{ perror("bind"); exit(1); }
									
	// ... allowing broadcast (optional)
	on=1;
	if(setsockopt(binUdpSocket,SOL_SOCKET,SO_BROADCAST,&on,sizeof(int))==-1)
	  { perror("setsockopt"); exit(1); }

	for(;;)
	  {
			  //---- wait for incoming informations ----
			  FD_ZERO(&rdSet);
			  FD_SET(0,&rdSet); // standard input
			  FD_SET(txtUdpSocket,&rdSet);
			  FD_SET(binUdpSocket,&rdSet);
			  int maxFd=txtUdpSocket>binUdpSocket ? txtUdpSocket : binUdpSocket;
			  // SELECT
			  if(select(maxFd+1,&rdSet,(fd_set *)0,(fd_set *)0,(struct timeval *)0)==-1)
											{ perror("select"); exit(1); }

			  //---- display standard input (if available) ----
			  if(FD_ISSET(0,&rdSet))
				{
					if(fgets(msg,0x100,stdin))
					  {
						printf("standard input: %s\n",msg);
					  }
				}

			  //---- receive text message (if available) ----
			  if(FD_ISSET(txtUdpSocket,&rdSet))
				{
					socklen_t len=sizeof(fromAddr);
					int r=recvfrom(txtUdpSocket,msg,0x100,0,(struct sockaddr *)&fromAddr,&len);
					if(r==-1)
										{ perror("recvfrom"); exit(1); }
					//---- display message and source address/port ----
					msg[r]='\0';
					printf("text message from %s:%d : %s\n", inet_ntoa(fromAddr.sin_addr),ntohs(fromAddr.sin_port),msg);
				}

			  //---- receive 32-bit value (if available) ----
			  if(FD_ISSET(binUdpSocket,&rdSet))
				{
					socklen_t len=sizeof(fromAddr);
					int r=recvfrom(binUdpSocket,&value,4,0,(struct sockaddr *)&fromAddr,&len);
					if(r==-1)
												{ perror("recvfrom"); exit(1); }
					//---- convert to host format 32-bit integer ----
					if(r<4)
												{ fprintf(stderr,"4 bytes expected\n"); exit(1); }
					value=ntohl(value);
					//---- display value and source address/port ----
					printf("binary value from %s:%d : %d\n", inet_ntoa(fromAddr.sin_addr),ntohs(fromAddr.sin_port),value);
				}
	  }

	close(txtUdpSocket);
	close(binUdpSocket);
	return 0;
}

//----------------------------------------------------------------------------

TCP mono server

TCP is a CONNECTED protocole, so before sending and receiving datas, the server must accept a client connection request.
For the moment the actual client must end the connection before the server accepts a new client.

tcp_mono
tcp_mono
{: .image_center height=“auto” width=“1000px” }

# CLIENT SIDE : PC
$ ./prog05_tcp_client 192.168.0.2 2000
456
4 bytes received
abcdef
7 bytes received
# SERVER SIDE : RPI
$ ./prog05_tcp_mono_server 2000
new connection from 192.168.0.2:60540
456

abcdef
prog05_tcp
#include "main.h"
//======================================================================
//						MAIN
//======================================================================
int main(int argc, char **argv)
{
	int portNumber;
	struct sockaddr_in toAddr;
	int ok;
	char buffer[0x100];
	
	//---- check command line arguments ----
	if(argc!=3)
				{ fprintf(stderr,"usage: %s destination port\n",argv[0]); exit(1); }

	//---- extract destination IP address ----
	struct hostent *host=gethostbyname(argv[1]);
	if(!host)
				{ fprintf(stderr,"unknown host %s\n",argv[1]); exit(1); }
	in_addr_t ipAddress=*((in_addr_t *)(host->h_addr));

	//---- extract destination port number ----
	if(sscanf(argv[2],"%d",&portNumber)!=1)
				{ fprintf(stderr,"invalid port %s\n",argv[2]); exit(1); }

	//---- create client socket ----
	int clientSocket=socket(PF_INET,SOCK_STREAM,0);
	if(clientSocket==-1)
				{ perror("socket"); exit(1); }
	  
	// ... connected to the specified destination/port
	toAddr.sin_family=AF_INET;
	toAddr.sin_port=htons(portNumber);
	toAddr.sin_addr.s_addr=ipAddress;
	ok = connect(clientSocket,(struct sockaddr *)&toAddr,sizeof(toAddr));
				if( ok == -1 ) { perror("connect"); exit(1); }

	#if 0
	  for(;;)
		{
			//---- read next line on standard input ----
			if(!fgets(buffer,0x100,stdin)) { break; } // [Control]+[d] --> EOF
		  
			//---- send message to server ----
			ok = send(clientSocket,buffer,strlen(buffer),0);
				if( ok == -1 ) { perror("send"); exit(1); }
		  
			//---- receive and display reply ----
			int nb=recv(clientSocket,buffer,0x100,0);
			if(nb<=0) { break; } // EOF
			buffer[nb]='\0';
			printf("%s\n",buffer);
		}
	#else
	  for(;;)
		{

		//---- wait for incoming informations ----
		fd_set rdSet;
		FD_ZERO(&rdSet);
		FD_SET(0,&rdSet); // standard input
		FD_SET(clientSocket,&rdSet);
		int maxFd=clientSocket;
		ok = select(maxFd+1,&rdSet,(fd_set *)0,(fd_set *)0,(struct timeval *)0);
						if( ok == -1 ) { perror("select"); exit(1); }

		//---- read next line on standard input (if available) ----
		if(FD_ISSET(0,&rdSet))
		  {
			  if(!fgets(buffer,0x100,stdin)) { break; } // [Control]+[d] --> EOF
			  //---- send message to server ----
			  ok = send(clientSocket,buffer,strlen(buffer),0);
						if( ok == -1 ) { perror("send"); exit(1); }
		  }
	  
		//---- receive and display reply (if available) ----
		if(FD_ISSET(clientSocket,&rdSet))
		  {
			  int nb=recv(clientSocket,buffer,0x100,0);
			  if(nb<=0) { break; } // EOF
			  buffer[nb]='\0';
			  printf("%s",buffer); fflush(stdout);
		  }
		}
	#endif

	//---- close client socket ----
	close(clientSocket);
	return 0;
}

//----------------------------------------------------------------------------
#include "main.h"

//======================================================================
//						MAIN
//======================================================================
int main(int argc, char **argv)
{
	int portNumber;
	struct sockaddr_in myAddr;
	struct sockaddr_in fromAddr;	
	int ok;
	char buffer[0x100];
	
	//---- check command line arguments ----
	if(argc!=2)
					{ fprintf(stderr,"usage: %s port\n",argv[0]); exit(1); }

	//---- extract local port number ----
	if(sscanf(argv[1],"%d",&portNumber)!=1)
					{ fprintf(stderr,"invalid port %s\n",argv[1]); exit(1); }

	//---- create listen socket ----
	int listenSocket=socket(PF_INET,SOCK_STREAM,0);
	if(listenSocket==-1)
					{ perror("socket"); exit(1); }
					
	// ... avoiding timewait problems (optional)
	int on=1;
	ok = setsockopt(listenSocket,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(int));
						if( ok == -1 ){ perror("setsockopt"); exit(1); }
						
	// ... bound to any local address on the specified port
	myAddr.sin_family=AF_INET;
	myAddr.sin_port=htons(portNumber);
	myAddr.sin_addr.s_addr=htonl(INADDR_ANY);
	ok = bind(listenSocket,(struct sockaddr *)&myAddr,sizeof(myAddr));
						if( ok == -1 ){ perror("bind"); exit(1); }
						
	// ... listening connections
	ok = listen(listenSocket,10);
						if( ok == -1 ){ perror("listen"); exit(1); }

	for(;;)	// 1st LOOP : ACCEPT CLIENTS
	  {
		  //---- accept new connection ----
		  socklen_t len=sizeof(fromAddr);
		  int dialogSocket=accept(listenSocket,(struct sockaddr *)&fromAddr,&len);
		  if(dialogSocket==-1)
							{ perror("accept"); exit(1); }
		  printf("new connection from %s:%d\n", inet_ntoa(fromAddr.sin_addr),ntohs(fromAddr.sin_port));

		  for(;;) // 2nd LOOP : RECEIVE MESSAGES
			{
					//---- receive and display message from client ----
					int nb=recv(dialogSocket,buffer,0x100,0);
					if(nb<=0) { break; } // EOF
					buffer[nb]='\0';
					printf("%s\n",buffer);

					//---- send reply to client ----
					nb=sprintf(buffer,"%d bytes received\n",nb);
					ok = send(dialogSocket,buffer,nb,0);
								if( ok == -1 ){ perror("send"); exit(1); }
			}

		  //---- close dialog socket ----
		  printf("client disconnected\n");
		  close(dialogSocket);
	  }

	close(listenSocket);
	return 0;
}

//----------------------------------------------------------------------------

TCP Select server

The Select Function permits switching between several sockets and listening for new TCP connections.

tcp_select1.svg

tcp_select2.svg

# APP CLIENT 1 : PC
$ ./prog05_tcp_client 192.168.0.2 2000
abcd
5 bytes received
123
4 bytes received

  

# APP CLIENT 2 : PC
e$ ./prog05_tcp_client 192.168.0.2 2000
123
4 bytes received
abcd
5 bytes received
# SERVER SIDE : RPI
$ ./prog05_tcp_select_server 2000
new connection from 192.168.0.2:50000
abcd

new connection from 192.168.0.2:50001
123

abcd

123
prog05_tcp_select_server.c
#include "main.h"

//======================================================================
//						MAIN
//======================================================================
int main(int argc, char **argv)
{
	int portNumber;
	struct sockaddr_in myAddr;
	int ok;
	int clients[0x100];
	int nbClients=0;
	
	int i;
	struct sockaddr_in fromAddr;
	char buffer[0x100];
	
	//---- check command line arguments ----
	if(argc!=2)
				{ fprintf(stderr,"usage: %s port\n",argv[0]); exit(1); }

	//---- extract local port number ----
	if(sscanf(argv[1],"%d",&portNumber)!=1)
				{ fprintf(stderr,"invalid port %s\n",argv[1]); exit(1); }

	//---- create listen socket ----
	int listenSocket=socket(PF_INET,SOCK_STREAM,0);
	if(listenSocket==-1)
				{ perror("socket"); exit(1); }
				
	// ... avoiding timewait problems (optional)
	int on=1;
	ok = setsockopt(listenSocket,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(int));
								if( ok == -1 ){ perror("setsockopt"); exit(1); }
	  
	// ... bound to any local address on the specified port
	myAddr.sin_family=AF_INET;
	myAddr.sin_port=htons(portNumber);
	myAddr.sin_addr.s_addr=htonl(INADDR_ANY);
	ok = bind(listenSocket,(struct sockaddr *)&myAddr,sizeof(myAddr));
								if( ok == -1 ){ perror("bind"); exit(1); }
	// ... listening connections
	ok = listen(listenSocket,10);
								if( ok == -1 ){ perror("listen"); exit(1); }


	for(;;)
	  {
				  //---- wait for new connections or incoming messages ----
				  fd_set rdSet;
				  FD_ZERO(&rdSet);
				  FD_SET(listenSocket,&rdSet);
				  int maxFd=listenSocket;
		
				  for(i=0;i<nbClients;++i)
					{
						FD_SET(clients[i],&rdSet);
						if(clients[i]>maxFd) maxFd=clients[i];
					}
				  ok = select(maxFd+1,&rdSet,(fd_set *)0,(fd_set *)0,(struct timeval *)0);
								if( ok == -1 ){ perror("select"); exit(1); }

				  //---- accept and store new connection (if available) ----
				  if(FD_ISSET(listenSocket,&rdSet))
					{

						socklen_t len=sizeof(fromAddr);
						int dialogSocket=accept(listenSocket,(struct sockaddr *)&fromAddr,&len);
						if(dialogSocket==-1)
									{ perror("accept"); exit(1); }
						printf("new connection from %s:%d\n",inet_ntoa(fromAddr.sin_addr),ntohs(fromAddr.sin_port));
						clients[nbClients++]=dialogSocket;
					}

				  //---- dialog with each client providing a message ----
				  for(i=nbClients;i--;)
					{
							int dialogSocket=clients[i];
							if(FD_ISSET(dialogSocket,&rdSet))
							  {
								  //---- receive and display message from client (if available) ----
								  int nb=recv(dialogSocket,buffer,0x100,0);
								  if(nb<=0)
									{
										printf("client disconnected\n");
										close(dialogSocket);
										clients[i]=clients[--nbClients];
									}
								  else
									{
										buffer[nb]='\0';
										printf("%s\n",buffer);
										//---- send reply to client ----
										nb=sprintf(buffer,"%d bytes received\n",nb);
										ok = send(dialogSocket,buffer,nb,0);
														if( ok == -1 ){ perror("send"); exit(1); }
									}
							  }
					}
	  }
	close(listenSocket);
	return 0;
	}

//----------------------------------------------------------------------------

TCP Thread server

A more flexible server than the ‘select’ one : allowing a thread for each client.
The FOR loop in the main() wait on new connection requests.

tcp_thread_1.svg

tcp_thread_2.svg

tcp_thread_3.svg

# APP CLIENT 1 : PC
$ ./prog05_tcp_client 192.168.0.2 2000
abcd
5 bytes received
89
3 bytes received

  

# APP CLIENT 2 : PC
./prog05_tcp_client 192.168.0.2 2000
1234
5 bytes received
popo
5 bytes received
# SERVER SIDE : RPI
./prog05_tcp_thread_server 2000
new connection from 192.168.0.2:50000
new connection from 192.168.0.2:50001
1234

abcd

popo

89
prog05_tcp_thread_server.c
#include "main.h"

//======================================================================

void * dialogThread(void *arg)
{
	char buffer[0x100];
	int ok;
	
	pthread_detach(pthread_self());
	//---- obtain dialog socket from arg ----
	int dialogSocket=*(int*)arg;
	free(arg);
	for(;;)
	  {
			  //---- receive and display message from client ----
			  int nb=recv(dialogSocket,buffer,0x100,0);
			  if(nb<=0) { break; }
			  buffer[nb]='\0';
			  printf("%s\n",buffer);

			  //---- send reply to client ----
			  nb=sprintf(buffer,"%d bytes received\n",nb);
			  ok = send(dialogSocket,buffer,nb,0);
									if( ok == -1 ){ perror("send"); exit(1); }
	  }

	//---- close dialog socket ----
	printf("client disconnected\n");
	close(dialogSocket);
	return (void *)0;
}

//======================================================================
//						MAIN
//======================================================================

int main(int argc,  char **argv)
{
	int ok;
	int portNumber;
	struct sockaddr_in myAddr;
	struct sockaddr_in fromAddr;
	
	//---- check command line arguments ----
	if(argc!=2)
				{ fprintf(stderr,"usage: %s port\n",argv[0]); exit(1); }

	//---- extract local port number ----
	ok = sscanf(argv[1],"%d",&portNumber);
				if( ok == -1 ){ fprintf(stderr,"invalid port %s\n",argv[1]); exit(1); }

	//---- create listen socket ----
	int listenSocket=socket(PF_INET,SOCK_STREAM,0);
	if(listenSocket==-1)
				{ perror("socket"); exit(1); }
	// ... avoiding timewait problems (optional)
	int on=1;
	ok = setsockopt(listenSocket,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(int));
				if( ok == -1 ){ perror("setsockopt"); exit(1); }
				
	// ... bound to any local address on the specified port
	myAddr.sin_family=AF_INET;
	myAddr.sin_port=htons(portNumber);
	myAddr.sin_addr.s_addr=htonl(INADDR_ANY);
	if(bind(listenSocket,(struct sockaddr *)&myAddr,sizeof(myAddr))==-1)
	  { perror("bind"); exit(1); }
	// ... listening connections
	if(listen(listenSocket,10)==-1)
							{ perror("listen"); exit(1); }

	for(;;)
	  {
		  //---- accept new connection ----
		  socklen_t len=sizeof(fromAddr);
		  int dialogSocket=accept(listenSocket,(struct sockaddr *)&fromAddr,&len);
		  if(dialogSocket==-1)
							{ perror("accept"); exit(1); }
		  printf("new connection from %s:%d\n",
				 inet_ntoa(fromAddr.sin_addr),ntohs(fromAddr.sin_port));

		  //---- start a new dialog thread ----
		  pthread_t th;
		  int *arg=(int *)malloc(sizeof(int));
		  *arg=dialogSocket;
		  if(pthread_create(&th,(pthread_attr_t *)0,dialogThread,arg))
							{ fprintf(stderr,"cannot create thread\n"); exit(1); }
	  }
	  
	close(listenSocket);
	return 0;
}

//----------------------------------------------------------------------------