服务器的基本问题避免

来源:互联网 发布:环保软件项目 编辑:程序博客网 时间:2024/06/08 19:16
TCP/IP协议的 11 中状态;

 

开发服务器中避免出现的问题:

一。服务器中表面出现僵尸进程:(SIGCHLD信号的处理)

1. 多进程服务器; 一个管理进程, 当客户端链接时, 起一个子进程与客户端进程通信;

2. 客户端:普通客户端程序, 与服务器之间保持长链接。

3.问题:

  此时设计到一个问题,当起 n 个客户端连接服务器时;服务器会产生 n 个子线程,用于各客户端通信,此时,加入一个客户端主动关闭链接,

  服务器应该关掉它对应的子进程,并对这个子进程进行回收,防止产生僵尸进程。

  ① 注册信号,当客户端主动断开连接, 服务器子进程会退出, 此时会向父进程,发送 SIGCHID  信号;父进程注册信号处理函数; signal(SIGCHID, func_data);

  func_data()   {   wait(NULL); }    (伪代码, 该函数的格式不对)。

  会调用该信号函数回收子进程;

  ②加入:多个链接客户端同时关闭连接, 此时会同时向服务器发送:FIN标识位,服务器多个子进程同时退出, 并同时向主进程 发出SIGCHID信号; 这时,上面的

  程序设计就出现问题。 因为: SIGCHID 信号是不可靠信号,当多个信号同时向父进程发送时, 服务器主进程可能回处理 1 个, 或多个 < n, 或者n个(理想状态),那么就会有很大可能产生僵尸进程。  为了避免这种情况的发生; 上面的信号注册函数, 就应该写成这样, 才可以避免该问题。

  func_data()   { int mypid = 0;  while( ( mypid = waitpid(-1, NULL, WNOHANG ) ) > 0 { ; (此处循环可以为空)} } 。

 

 二。通信中出现SIGPIPE信号:(SIGPIPE信号的处理和该信号出现的时机)

  1. 在网路通信中, 因为套接字为 全双工通信;

   当 server 关闭 一个套接字后,client 继续向该套接字发送消息, 按照 TCP 协议规定, client 会收到一个RST响应, client再用该套接字向 server发送数据时,

  会收到SIGPIPE信号, 该信号的默认处理方式:终端当前进程;如果不对该信号进行处理,会造成当前的程序不稳定, 出现上述情况时,会使client 退出。

  (server端亦然);

  2.  为避免程序退出, 就需要对该信号进行处理, 两种方式: 1. 忽略该信号 signal(SIGPIPE, SIG_IGN); 2.捕捉该信号signal(SIGPIPE, 捕捉函数);

  3.对于产生信号,我们可以在产生信号前利用方法 signal(int signum, sighandler_t handler) 设置信号的处理。如果没有调用此方法,系统就会调用

  默认处理方法:中止程序,显示提示信息(就是我们经常遇到的问题)。我们可以调用系统的处理方法,也可以自定义处理方法。 

  系统里边定义了三种处理方法: 
  (1)SIG_DFL信号专用的默认动作:
    (a)如果默认动作是暂停线程,则该线程的执行被暂时挂起。当线程暂停期间,发送给线程的任何附加信号都不交付,直到该线程开始执行,但是SIGKILL除外。
    (b)把挂起信号的信号动作设置成SIG_DFL,且其默认动作是忽略信号 (SIGCHLD)。
  (2)SIG_IGN忽略信号
    (a)该信号的交付对线程没有影响
    (b)系统不允许把SIGKILL或SIGTOP信号的动作设置为SIG_DFL
  (3)SIG_ERR   

  项目中我调用了signal(SIGPIPESIG_IGN), 这样产生  SIGPIPE 信号时就不会中止程序,直接把这个信号忽略掉。

 

三。close与shutdown的区别:(调用方式产生的不同效果,以及他们俩的实现基本原理)

  close() 与shutdown() 关闭套接字的区别:

  1.close(): 采用 引用计数技术;只有当关闭的套接字: 基数为0时, TCP协议 才会向对端发送 FIN 标识符, 表示该套接字关闭;

  2.shutdown(): 只要调该函数关闭套接字: 就会向对端发送 FIN 标识符, 表示 该套接字关闭;

    1.该函数的3种关闭方式: 

          1.SHUT_RD:值为0,关闭连接的读这一半。

          2.SHUT_WR:值为1,关闭连接的写这一半。

          3.SHUT_RDWR:值为2,连接的读和写都关闭。

  3.close与shutdown的区别主要表现在:

         close函数会关闭套接字ID,如果有其他的进程共享着这个套接字,那么它仍然是打开的,这个连接仍然可以用来读和写,并且有时候这是非常重要的 ,

  特别是对于多进程并发服务器来说。

         而shutdown会切断进程共享的套接字的所有连接,不管这个套接字的引用计数是否为零,那些试图读得进程将会接收到EOF标识,那些试图写的进程

  将会检测到SIGPIPE信号,同时可利用shutdown的第二个参数选择断连的方式。

 

四。长链接、短链接

  1.长链接: 表示一直链接, 不断开;

    while(1){

      write();

      read();

    }close();

  2.短链接:发送完数据后,就断开。

     {    //该数据一轮 收发完后, 立即断开。

      write();

      read();

      close();   

    }

 

0 0
原创粉丝点击