以多进程来并发的socket服务端

一。

pid_t pid;

int listenfd, connfd;

listendfd = Socket(...);

Bind();

Listen(..);

for()

{

connfd = Accept(xxx);

if( pid = Fork() == 0){

 Close(listenfd); 子关闭监听sockfd  情况1,

 doit(connfd);

 Close(connfd); 子运行完了然后关闭自己的sockfd

 exit(0);

}

 Close(connfd); 父关闭子fd          情况3

}

fork了一个子进程后,则表明现在已经有两个进程具有相同的东东了,描述符,环境及变量值。

注意:父进程关闭了子sockfd,子进程关闭了父进程sockfd.

其实他们并没有关闭,只是文件描述符的特性是酱紫滴:文件描述符都有一个引用计数特性,由于子进程复制了一份父进程的所有东东,那么描述符的引用计数就+1了,由原来只有父进程的1个引用,变成了2.

这就表示,close()的时候呢,仅仅只是吧引用计数减1,知道减到0了,才真正的释放该描述符。所以,情况1,情况3,是不会真正释放滴。

如果想让fd在计数符号>1的情况下发送FIN给对端,那么可以使用shutdown()函数。

1.大家发现,服务器的子进程终止后,进入了僵死进程。僵死进程会占用系统资源。这些进程保留了该进程的一些信息,比如cpu时间等等以方便他的父进程来调。

他们之所以会成为僵死进程,是因为他们在结束的时候,发送sigchld信号给父进程,但是父进程却没有对该信号做处理,该信号的默认行为是被忽略。只要父进程不死,那么这些僵死进程也会一直存在,那么终会导致资源消耗。

因为僵死进程要彻底挂,得他的父进程挂了,然后他的父进程由内核指定为Init进程,这样init进程就会在一定时间后定时清理这些僵死进程。

2.要解决僵死进程的做法是,父进程必须要waitpid他们。只要他们发送sigchld信号来,我们注册该信号函数,并在函数里面调用wait,那么就可以表示该子进程挂的时候找到了归宿的感觉,它才挂的瞑目。sigcation()函数,就是信号注册函数。

呵呵,其实wait和waitpid的目的就是清理已经终止的子进程啦。我类歌曲。

3.有两个信号不能被捕获:sigkill sigstop. 同时这两个信号也不能被忽略。

4.信号处理函数期间,同类信号的来到是阻塞的。而且阻塞期间,多个同类信号会作为一个信号提交。(即默认不排队的),怎么解决呢?用waitpid即可。

5.系统调用在被信号中断的时候,会返回一个EINTR -intr的错误,表示被信号中断鸟。有些系统调用会自动重启来过,有些则不会。这个就需要我们处理好鸟。

6.服务器进程挂了,但是tcp客户依旧可以发送信号给服务器主机,因为那是在tcp层的数据处理,tcp层发现对应端口的服务器进程木有,那他就反回对端一个RST表示木有进程对你服务。

7.当一个进程接受到RST并且还固执的要求对该tcp进行写操作的时候,内核会对该进程发送一个sigpipe信号,该信号默认行为是终止进程。如果你不想被他挂,你可以捕获该信号。而且写操作会返回epipe.

8.检测主机服务器崩溃有一个技术:so_keepalive套接字选项:及时客户不发数据给服务端,也能够检测出服务端是否挂没挂。客户/服务心搏函数。

9. close()是关闭双工连接,而shutdown()则可以关闭半链接。其中有参数设置:SHUT_RD关闭链接的读这一半,SHUT_WR关闭连接的写这一半,SHUT_RDWR读写都关闭

1.




你可能感兴趣的:(网络编程)