一个服务器和多个客户端进行通信

多线程处理

服务器端

accept()放在线程函数中可能会造成的问题:
有可能多个线程同时去已完成三次握手的队列中建立链接,这时候需要加锁。以保证互斥的访问。

#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<stdio.h>
#include<assert.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<pthread.h>
void *thread_fun(void *arg)
{
	
		int c=(int)arg;
	    
		while(1)
		{
			char buff[128]={0};
			int n=recv(c,buff,127,0);
			 if(n<=0)
			{			
				break;
			}
			printf("rccv(%d)=%s\n",c,buff);
			send(c,"ok",2,0);
		}
        	
        close(c);
		printf("one client over\n");
	

}



int main()
{
    
    pthread_t  thread;

	int sockfd=socket(AF_INET,SOCK_STREAM,0);
	assert(sockfd!=-1);

	struct  sockaddr_in  saddr,caddr;
	memset(&saddr,0,sizeof(saddr));
    
	saddr.sin_family=AF_INET;
	saddr.sin_port=htons(6000);//1024 root,4096 reserve,5000+ tempary
    saddr.sin_addr.s_addr=inet_addr("127.0.0.1");

	int res=bind(sockfd,(struct sockaddr *)&saddr,sizeof(saddr));
	assert(res!=-1);
	
	listen(sockfd,5);//create listen queue

	while(1)
	{
		int len=sizeof(caddr);
		int c=accept(sockfd,(struct sockaddr *)&caddr,&len);
		if(c<0)
		{
			continue;
		
		}
	  printf("accept c=%d,ip=%s,port=%d\n",c,inet_ntoa(caddr.sin_addr),ntohs(caddr.sin_port));
	
	   pthread_create(&thread,NULL,thread_fun,(void *)c);
	
   }
   close(sockfd);
}

客户端

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

int main()
{
	int sockfd=socket(AF_INET,SOCK_STREAM,0);
	assert(sockfd!=-1);

	struct sockaddr_in  saddr;
	memset(&saddr,0,sizeof(saddr));
	saddr.sin_family=AF_INET;
	saddr.sin_port=htons(6000);
    saddr.sin_addr.s_addr=inet_addr("127.0.0.1");

	int res=connect(sockfd,(struct sockaddr *)&saddr,sizeof(saddr));
	assert(res!=-1);
    
	while(1)
	{
		char buff[128]={0};
		printf("input:\n");
		fgets(buff,128,stdin);

		if(strncmp(buff,"end",3)==0)
		{
			break;
		}
		send(sockfd,buff,strlen(buff),0);
		//write(sockfd,buff,strlen(buff));
		memset(buff,0,128);
		recv(sockfd,buff,127,0);
		printf("buff=%s\n",buff);
	}
	close(sockfd);
}

多进程处理

服务器端

fork()之后c的引用计数加1,主进程不用,一定要close©
存在的问题:当多个线程在同一时刻结束时,父进程只能处理一个,其他子进程没办法处理,可以采用waitpid()函数进行处理,waitpid()返回值为0,我们可以认为还有僵死进程,接着循环进行处理,否则认为僵死进程已经处理完了,结束循环。

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

void sig_fun(int sig)
{
	int val=0;
	wait(&val);//收到信号后,等待子进程结束

}



int main()
{
	int sockfd=socket(AF_INET,SOCK_STREAM,0);
	assert(sockfd!=-1);

	struct  sockaddr_in  saddr,caddr;
	memset(&saddr,0,sizeof(saddr));
    
	saddr.sin_family=AF_INET;
	saddr.sin_port=htons(6000);//1024 root,4096 reserve,5000+ tempary
    saddr.sin_addr.s_addr=inet_addr("127.0.0.1");

	int res=bind(sockfd,(struct sockaddr *)&saddr,sizeof(saddr));
	assert(res!=-1);
	
	listen(sockfd,5);//create listen queue

	signal(SIGCHLD,sig_fun);
    pid_t pid;
	while(1)
	{
		int len=sizeof(caddr);
		int c=accept(sockfd,(struct sockaddr *)&caddr,&len);
		if(c<0)
		{
			continue;
		
		}

	 printf("accept c=%d,ip=%s,port=%d\n",c,inet_ntoa(caddr.sin_addr),ntohs(caddr.sin_port));
	 
	 
	 pid=fork();
	 if(pid==-1)
	 {
		close(c);
		continue;
	 }
	 if(pid==0)
	 {
	
	    while(1)
		{
			char buff[128]={0};
			int n=recv(c,buff,127,0);
	        if(n<=0)
			{
				break;
			}
			printf("buff=%s\n",buff);
			send(c,"ok",2,0);
		}

	    close(c);
		printf("one client over\n");
		exit(0);
   	}
	close(c);
  }
  close(sockfd);
  exit(0);
  }

客户端

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

int main()
{
	int sockfd=socket(AF_INET,SOCK_STREAM,0);
	assert(sockfd!=-1);

	struct sockaddr_in  saddr;
	memset(&saddr,0,sizeof(saddr));
	saddr.sin_family=AF_INET;
	saddr.sin_port=htons(6000);
    saddr.sin_addr.s_addr=inet_addr("127.0.0.1");

	int res=connect(sockfd,(struct sockaddr *)&saddr,sizeof(saddr));
	assert(res!=-1);
    
	while(1)
	{
		char buff[128]={0};
		printf("input:\n");
		fgets(buff,128,stdin);

		if(strncmp(buff,"end",3)==0)
		{
			break;
		}
		send(sockfd,buff,strlen(buff),0);
		//write(sockfd,buff,strlen(buff));
		memset(buff,0,128);
		recv(sockfd,buff,127,0);
		printf("buff=%s\n",buff);
	}
	close(sockfd);
}

猜你喜欢

转载自blog.csdn.net/qq_43313035/article/details/89066154