Chinaunix首页 | 论坛 | 博客
  • 博客访问: 236031
  • 博文数量: 59
  • 博客积分: 4010
  • 博客等级: 上校
  • 技术积分: 900
  • 用 户 组: 普通用户
  • 注册时间: 2009-03-30 20:21
文章分类

全部博文(59)

文章存档

2011年(1)

2009年(58)

我的朋友

分类: 系统运维

2009-04-05 21:40:02

看了Unix网络编程五、六章,小结一下,以备复习。

1,如果采用并发服务器形式,则需要处理子进程消亡后的僵死进程,即对SIGCHLD信号的处理。这里又涉及到wait和waitpid的选择问题,书中指出,wait并不足以防止出现僵死进程,我们应用采用:
void sig_chid( int signo )
{
     pid_t pid;
     int stat;

     while ((pid=waitpid(-1, &stat, WNOHANG)) > 0 )
           {
               printf( "child %d terminated\n", pid );
          }
     return;
}
2,对于TCP连接的中止,正常的就不用提了,异常的话有两种情况,一是服务器进程中止,另一种是服务器主机崩溃。
   当服务器进程中止的时候,服务器会向客户机发送一个FIN信号,以完成连接中止的一半操作。然而,FIN信号的接受并没有告诉客户端服务器进程已经终止,只是表示服务器不会再往其中发任何数据。此后如果服务器接受到来自客户的数据,由于先前打开的那个套接口的进程已经终止,于是会响应一个RST。但是由于客户端在调用write函数后会立即调用read函数,由于已经接受到FIN信号了,所以read会立即返回,从而收不到这个RST。而如果我们在read之前调用sleep,将其睡眠一定时间,了就是read发生在收到RST之前,那么结果是客户得到一个未预期的EOF,否则结果是返回一个ECONNRESET错误。而如果客户并不理会read返回的错误还继续往服务器发送数据呢?其结果是内核将向该进程发送一个SIGPIPE信号,该信号的缺省行为是终止进程。
    出现上面问题的根本原因是客户实际上对应两个描述字,套接口和用户输入,它不能单纯阻塞在这两个源中的某个特定源的输入上,而是应该阻塞在其中任何一个源的输入上。也就是说只要任何一个不可用,就应该返回。
   解决的办法是使用select,pselect或poll函数。
   #include
   #include
   int select( int maxfdpl, fd_set* readset, fd_set* writeset, fd_set* exceptset,
               const struct timeval* timeout );
其中的timeval结构用于指定这段时间的秒数的微秒数。
   struct timeval {
          long tv_sec; /*seconds     */
          long tc_usec;/*microseconds*/
};
当其为NULL时,将永远等待下去;当其为0时,立即返回;当其为一个不为0的数时,等待指定的时间后返回。
另外要注意的一点是,第一个参数指定的是描述字的个数而非最大值,而描述字是从零开始的,所以此值应该为最大描述字再加1,忘记加1是一个常犯的错误。
有一组宏对描述字集进行操作:
void FD_ZERO( fd_set* fdset );
void FD_SET( int fd, fd_set* fdset );
void FD_CLR( int fd, fd_set* fdset );
int FD_ISSET( int fd, fd_set* fdset);
需要注意的一点是,每次重新调用select时,我们都应该再次把所有描述字集中所关心的位均置为1。

如果服务器主机崩溃,那么已有的网络连接上发不出任何东西,这种情况只有在我们向服务器发送数据后才能检测到它已经崩溃,如果我们不主动向它改善数据也想检测出服务器主机的崩溃,那么就得设置SO_KEEPALIVE套接口选项。
阅读(870) | 评论(0) | 转发(0) |
0

上一篇:流行语录

下一篇:李小龙简介

给主人留下些什么吧!~~