一、多进程编程
1、多进程处理
单机处理不能同时处理两个客户端,因为一旦一方执行起来,获取连接就会一直在while循环里面,而另一方获取不到连接,无法通讯,所以采用多进程处理。
思路:父进程只负责获取连接,然后fork出子进程去和客户端通讯。
注意:父子进程共享文件描述符,所以子进程在通讯时不必再创建文件描述符; 父进程创建出子进程后,关闭获取连接的文件描述符。
利用父子进程编程:
(1)服务器端代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <signal.h>
void fun(int sign)
{
wait(NULL);
}
int main ( )
{
signal(SIGCHLD,fun);
int sockfd = socket(AF_INET,SOCK_STREAM,0);
assert(sockfd!=-1);
struct sockaddr_in ser,cli;
memset(&ser,0,sizeof(ser));
ser.sin_family = AF_INET;
ser.sin_port = htons(6000);
ser.sin_addr.s_addr = inet_addr("127.0.0.1");
int res = bind (sockfd,(struct sockaddr *)&ser,sizeof(ser));
assert(res!=-1);
listen(sockfd,5);
while(1)
{
int len = sizeof(cli);
int c = accept(sockfd,(struct sockaddr*)&cli,&len);
if( c < 0)
{
printf("error\n");
continue;
}
pid_t pid=fork();
assert(pid!=-1);
if(pid==0)
{
while(1)
{
char buff[128]={0};
int pid = recv(c,buff,127,0);
if (pid <= 0 )
{
break;
}
printf("addr:%s port:%d\n",inet_ntoa(cli.sin_addr),ntohs(cli.sin_port));
printf("%s\n",buff);
send(c,"ok",2,0);
}
printf ("%d unlink\n",c);
close(c);
exit(0);
}
close(c);
}
}
(2)客户端代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <fcntl.h>
int main ( )
{
int sockfd = socket(AF_INET,SOCK_STREAM,0);
assert(sockfd!=-1);
struct sockaddr_in ser,cli;
memset(&ser,0,sizeof(ser));
ser.sin_family = AF_INET;
ser.sin_port = htons(6000);
ser.sin_addr.s_addr = inet_addr("127.0.0.1");
int res = connect (sockfd,(struct sockaddr *)&ser,sizeof(ser));
assert(res!=-1);
while(1)
{
printf("please input:");
fflush(stdout);
char buff[128]={0};
fgets(buff,128,stdin);
if(strncmp(buff,"end",3) == 0)
{
close(sockfd);
break;
}
send(sockfd,buff,strlen(buff) - 1,0);
memset(buff,0,128);
recv(sockfd,buff,127,0);
printf("%s\n",buff);
}
}
运行结果如图: