您的位置:首页 > 理论基础 > 计算机网络

进程之间的通信--套接字(网络部分)

2017-11-15 13:26 387 查看
多进程网络编程:

在linux下创建一个新进程用的系统调用是fork()

使用头文件#include<sys/types.h>

                 #include<unistd.h>

                 pid_t fork(void);

此函数每次调用都返回两次,父进程返回的是子进程的PID,子进程返回0,根据其返回值可以判断其是子进程或是父进程,详细代码见后。

思想:在网络编程中,服务器与客户端进行连接服务,当服务器端连接上一个客户端时,当循环监听客户端发送的数据时,这使如果有另一个客户端进来连接服务器端就会失败,所以需要其减少服务器端的工作负担,因此产生一个子进程让子进程来分担服务器端的读取发送工作。在父进程可以不断接收客户端链接,链接之后产生子进程,让子进程去处理客户端的请求,达到效率的最大化


关于父子进程之间文件描述符问题:

在执行Fork函数之后,父进程中的文件描述符在子进程中默认也是打开的,且文件描述符的引用计数+1,父子进程共享一个文件描述符,其为浅拷贝。

也就是说当父进程关闭文件描述符时,子进程不受影响,因为在struct file中有一个计数器记录当前连接此文件的进程个数,当count为0才真正关闭文件描述符,而父进程关闭的只是他的指向

思考:为什么在多进程网络通讯中父进程fork()之后要关闭文件描述符?Close(c)

1、因为在不关闭的情况下,后续连接再次fork时,文件描述符不断增大,连接的客户端的数量就受到了限制(这个服务器所能连接的最大客户端数量变成系统中最多打开文件描述符的数量)

2、不关闭,fork之后,每个子线程都有struct file *指向我们的上次创建的文件描述符,也就是被继承下来,增加了代码处理的复杂性



拓:Linux限制命令:

ulimit -u查询最多限制的文件描述符的限制

  ulimit -hu 表示我们目前可以设置文件描述符限制到多大

ulimit -u +数据 设置其最多打开文件描述符的个数

服务器端代码:

#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
#include<assert.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
void main()
{

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

struct sockaddr_in ser,cli;
ser.sin_family=AF_INET;
ser.sin_port=htons(6000);//5000一下谨生使用 1024是电脑自身使用
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);
assert(c!=-1);
pid_t pid=fork();

if(pid==0)
{
while(1)
{
char buff[128]={0};
recv(c,buff,127,0);
printf("recv:%s\n",buff);
send(c,"ok",3,0);
}
}
close(c);
}
close(sockfd);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: