Implement a TCP concurrent server

1. Why TCP cannot achieve concurrency, but UDP can 

        Because the TCP server has two read blocking functions, accept and recv, the two functions need to be run one after the other, so the other function cannot be executed when one function is running, so it is impossible to guarantee communication with other clients while connecting to the client.

        UDP has only one blocking function recvfrom, and there is no need to connect, so concurrency can be achieved.

2. How to implement a TCP concurrent server

2.1. Two commonly used methods

        1. Use multi-process to realize TCP concurrent server
        2. Use multi-thread to realize TCP concurrent server

3. Use multi-process to realize TCP concurrent server

3.1, using multi-process to realize the simple process of TCP concurrent server

 int sockfd = socket() Create a socket
 bind() Bind your own information with the socket
 listen() Set the socket to passive listening state and set how many clients can be connected   at the same time
 while(1) { loop Wait, the client connects
 acceptfd = accept() receives the client's sockfd, and returns a dedicated client acceptfd identifier
 pid = fork(); create a parent-child process
 if(pid > 0) greater than 0 is the parent process
  { }
 else if(pid == 0) Equal to 0 is the child process
   {         while(1) communicates with the dedicated client    {       recv()/send() receive and receive     }}}



 Disadvantages: when the process ends, resources are not recycled, resulting in a waste of resources. The solution is to use the signal signal function to recycle the child process.

If you don't understand, please refer to the chapter of signal signal to learn.

3.2, using multi-process to realize TCP concurrent server code implementation

3.3, server code

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <sys/types.h>          
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <signal.h>
#include <sys/wait.h>
#include <unistd.h>

#define N 128

void handler()
{
	wait(NULL);
	
	
	}


int main(int argc , char *argv[])
{  
  	if(argc<3)
	{
		printf("fail : lose ip port\n");
		exit(1);
		
		}

     int sockfd;

	 signal(SIGCHLD,handler);


   	 if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
	 {
		 perror("fail to sockfd");
		 exit(1);
		 }
	 struct sockaddr_in mysockaddr;

	 mysockaddr.sin_family=AF_INET;
	 mysockaddr.sin_port = htons(atoi(argv[2]));
	 mysockaddr.sin_addr.s_addr =inet_addr(argv[1]);
     socklen_t addrlen =sizeof(mysockaddr);
   
   
 	 if(bind(sockfd,(struct sockaddr *)&mysockaddr,addrlen)==-1)
     {
		 perror("fail to bind");
		 exit(1);
		 }
	  
	   if(listen(sockfd,5)==-1)
	   {
		    perror("fail to listen");
		    exit(1);
		   }
      
        struct sockaddr_in acceptaddr;
        socklen_t acceptaddrlen=sizeof(acceptaddr);
        pid_t pid;
		int acceptfd;
	   while(1)
	   {
		   
	    if((acceptfd=accept(sockfd,(struct sockaddr*)&acceptaddr,&acceptaddrlen))==-1)
		{
			perror("fail to acceptfd");
			exit(1);
			
			}
		printf("reciver from ip = %s ,port:%d\n",inet_ntoa(acceptaddr.sin_addr),ntohs(acceptaddr.sin_port));


		pid=fork();

		if(pid<0)
		{
			
			perror("fail to fork");
			exit(1);

			}
		   
        else if(pid>0)
		{
			
			}

		  else
		  {

                 ssize_t byte;

			while(1)
			{
				char text[N]="";
				char buf[N]="";
    	        if((byte=recv(acceptfd,buf,N,0))==-1)
				{					
					perror("fail to recv");
					exit(1);
					}

                else if(byte==0)
				 {
					 printf("the client quit\n");
					 exit(1);
					 }
                   

 			    printf("from client :%s\n",buf);
				
                  
				 strcat(text,"^_^") ;

 				if(send(acceptfd,text,N,0)==-1)
				{
				perror("fail to ssend");
				exit(1);
					}
			  
			 } 
		  }	   
		   
		   }

	  return 0;
	}

3.4. Client code

#include<stdio.h>
#include<stdlib.h>
#include <sys/types.h>       
#include <sys/socket.h>
#include<string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <arpa/inet.h>
 
 
#define N 128
int main(int argc ,char *argv[])
{
	 if(argc<3)
	 {
		 printf("fail ,lose ip port\n");
		 exit(1);
		 
		 }
	 int sockfd;
 
	 if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
	 {
		 perror("fail to sockfd");
		 exit(1);
		 
		 }
 
//	  printf("TCP:sockfd= %d\n",sockfd);
        
      struct sockaddr_in mysockaddr;
 
	  mysockaddr.sin_family=AF_INET;
	  mysockaddr.sin_port=htons(atoi(argv[2]));
	  mysockaddr.sin_addr.s_addr=inet_addr(argv[1]);
	  socklen_t addrlen= sizeof(mysockaddr);
 
      if(connect(sockfd,(struct sockaddr*)&mysockaddr,addrlen)==-1)
	  {
		   perror("fail to connect");
		   exit(1);
		   }
	   
	  
	     char buf[N]="";
		 char text[N]="";
	while(1)
	{
		  fgets(buf,N,stdin);
          
		  if(send(sockfd,buf,N,0)==-1)
		  {
			  perror("fail to send");
			  exit(1);
			  
			  }
		  
	     
		 if(recv(sockfd,text,N,0)==-1)
		 {
	          perror("fail to recv");
			  exit(1);
 
			 }
		  
		  printf("from server: %s\n",text);
	    	  
       }    		  
		  close(sockfd);
	  
        	return 0;
	
	}
 

3.5. Running results

 

 Fourth, use multithreading to realize TCP concurrent server

4.1, multi-threaded implementation of simple process of TCP concurrent server

typedef struct { //Define a structure

       struct sockaddr_in addr; //Used to pass to child thread

       int acceptfd;      

} MSG;

 

  void *thread_fun(void *arg)          
  {    

         MSG msg = *(MSG *)arg; //The information of the client is passed to the child thread

while(1)
  {       recv() / send() // receive and receive  } }   sockfd = socket() //create socket   bind() //bind socket and own information   listen() // will Set the socket to passive listening state, and set how many clients can be connected  at the same time     while(1) //Loop waiting for client connection    {    accept() //Create an acceptfd identifier for the exclusive corresponding client     //As long as there is a client connection above, create a child thread to communicate with it   pthread_create(, , thread_fun, );             pthread_detach(); //Separate mode, automatically recycle resources, no waiting  }












 4.2, server code

#include<stdio.h>
#include <sys/types.h>          
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <pthread.h>
#include<string.h>
#include<unistd.h>


#define N 128
typedef struct
{
	struct sockaddr_in addr;
	  int acceptfd ;
	
	
	}MSG;

void * pthread_fun(void *arg)
{
	  char buf[N]="";
	  ssize_t size ;
	 MSG msg = *(MSG *)arg;
     while(1)
	 {
		 char text[N]="";
		 if((size=recv(msg.acceptfd,buf,N,0))==-1)
		 {
			 perror("fail to recv");
			 pthread_exit(NULL);
			 }
		 else if(size ==0)
		 {
			 perror("quit client");
			 pthread_exit(NULL);
			 
			 }
		 printf("[%s ‐ %d]: %s\n", inet_ntoa(msg.addr.sin_addr), ntohs(msg.addr.sin_port), buf);

         strcat(text," ^_^");

         if(send(msg.acceptfd,text,N,0)==-1)
		 {
			 perror("fail to send");
			 exit(1);
			 }
		 }	 
	
	 }

int main(int argc ,char *argv[])
{ 
     if(argc <3)
	 {
		 printf("fail ; lose ip port \n");
		 exit(1);
		 }

	 int sockfd;

	 if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
	 {
		 perror("fail to socket");
		 exit(1);

		 }
	 int on=1;

	 if(setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on))<0)
	 {
		 perror("fail to setsockopt");
		 exit(1);
		 }
    
	struct sockaddr_in mysockaddr;
	struct sockaddr_in clientaddr;

	mysockaddr.sin_family=AF_INET;
	mysockaddr.sin_port = htons(atoi(argv[2]));
	mysockaddr.sin_addr.s_addr=inet_addr(argv[1]);
	socklen_t socklen = sizeof(mysockaddr);

    socklen_t addrlen = sizeof(clientaddr);

    if(bind(sockfd,(struct sockaddr *)&mysockaddr,socklen)==-1)
	{
		perror("fail to bind");
		exit(1);
		}
	
	 if(listen(sockfd,5)==-1)
	 {
		 perror("fail to listen");
		 exit(1);
		 }
	  int acceptfd;
	 while(1)
	 {
		 if((acceptfd=accept(sockfd,(struct sockaddr *)&clientaddr,&addrlen))==-1)
		 {
			  perror("fail to accept");
			  exit(1);
			   }
		  MSG msg;
		  msg.addr = clientaddr;
          msg.acceptfd=acceptfd; 
		  
          pthread_t thread;

		  if(pthread_create(&thread,NULL,pthread_fun,&msg)!=0)
		{
			perror("fail to pthread_create");
			exit(1);

 			}	  
             pthread_detach(thread);

		  
		 }	
	
	return 0;
	      }

4.3. Client code

 

#include<stdio.h>
#include<stdlib.h>
#include <sys/types.h>       
#include <sys/socket.h>
#include<string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <arpa/inet.h>
 
 
#define N 128
int main(int argc ,char *argv[])
{
	 if(argc<3)
	 {
		 printf("fail ,lose ip port\n");
		 exit(1);
		 
		 }
	 int sockfd;
 
	 if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
	 {
		 perror("fail to sockfd");
		 exit(1);
		 
		 }
 
//	  printf("TCP:sockfd= %d\n",sockfd);
        
      struct sockaddr_in mysockaddr;
 
	  mysockaddr.sin_family=AF_INET;
	  mysockaddr.sin_port=htons(atoi(argv[2]));
	  mysockaddr.sin_addr.s_addr=inet_addr(argv[1]);
	  socklen_t addrlen= sizeof(mysockaddr);
 
      if(connect(sockfd,(struct sockaddr*)&mysockaddr,addrlen)==-1)
	  {
		   perror("fail to connect");
		   exit(1);
		   }
	   
	  
	     char buf[N]="";
		 char text[N]="";
	while(1)
	{
		  fgets(buf,N,stdin);
          
		  if(send(sockfd,buf,N,0)==-1)
		  {
			  perror("fail to send");
			  exit(1);
			  
			  }
		  
	     
		 if(recv(sockfd,text,N,0)==-1)
		 {
	          perror("fail to recv");
			  exit(1);
 
			 }
		  
		  printf("from server: %s\n",text);
	    	  
       }    		  
		  close(sockfd);
	  
        	return 0;
	
	}
 

4.4. Running results

Did you learn it?

 

 

Guess you like

Origin blog.csdn.net/weixin_47783699/article/details/128006471