zoukankan      html  css  js  c++  java
  • socket

    在做一个简单的socket程序时,遇到当client退出时,server状态为defunct情况。过程如下:

     (1)   Server  <--  Client

     (2)   Server (accept) <-X- Client
                       (fork)             |
                 New Server  <-----+

     (3)   Server            杀掉Client后
            New Server <defunct>

    原因:在子进程退出时,发送了SIGCHLD信号。

    解决方法在父进程中waitpid(); 可以获得子进程的退出状态

    
    
    void sig_chld (int signo) {
        pid_t pid;
        int stat;
    
        while ((pid = waitpid(-1,&stat, WNOHANG)) > 0)
            printf("child %d terminated\n",pid);
        return;
    }

    int main()
    {
    signal(SIGCHLD, sig_chld);
    //...
    fork();
    }

     也可以在父进程中忽略该信号

    signal(SIGCHLD,SIG_IGN); 

    下面是几个socket用到的属性介绍. 

    int socket(int domain, int type, int protocol);
    
    /* int type SOCK_CLOEXEC: 这个属性对应open函数的O_CLOEXEC 该标志作用为,当执行fork并执行exec的时候,在子进程中,自动关闭此描述符
    参考:http://blog.csdn.net/chrisniu1984/article/details/7050663
    */ /* 也可以通过如下代码设置 */
    int v;
    v
    = fcntl(fd, F_GETFD, 0);
    fcntl(fd, F_SETFD, v
    |FD_CLOEXEC);


    /* SO_REUSEADDR 仅仅表示可以重用本地本地地址、本地端口,整个相关五元组还是唯一确定的。
    * 所以,重启后的服务程序有可能收到非期望数据。必须慎重使用 SO_REUSEADDR 选项。
    * 如果你的服务程序停止后想立即重启,而新套接字依旧使用同一地址和端口,此时 SO_REUSEADDR 选项非常有用。
    */

    setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));


    /* fcntl(fd, F_SETFL, O_NONBLOCK);
    * 如果socket设置了如上属性,那么accept也将是非阻塞的。accept()函数会立即返回。
    * 注:没有数据时,会返回错误。
    */

    accept(s->fd, (struct sockaddr*)&cliaddr, &clilen);

    read 收包,判断是否一个接收已经完成了。

    /* 文件,socket 同理,read返回0时,才表示文件尾/数据包尾 */
    while(read(sock, buf, sizeof(buf)-1))
    {
      //数据放入缓冲区
    }
    /***********************************
    同时有如下内部逻辑
    TCP协议是面向流的,read和write调用的返回值往往小于参数指定的字节数。对于read调用,
    如果接收缓冲区中有20字节,请求读100个字节,就会返回20。对于write调用,如果请求写100个字节,
    而发送缓冲区中只有20个字节的空闲位置,那么write会阻塞,直到把100个字节全部交给发送缓冲区才返回,
    但如果socket文件描述符有O_NONBLOCK标志,则write不阻塞,直接返回20
    ***********************************/
  • 相关阅读:
    Java正式day_06——数组排序
    别只知道策略模式+简单工厂,试试更香的策略模式+抽象工厂!
    图解连接阿里云(一)创建阿里云物联网平台产品和设备,使用MQTT.fx快速体验
    嵌入式交叉编译GDB,结合vscode图形化调试C和C++代码 coredump定位段错误
    内核链表之list_for_eacy_entry手绘图解
    makefile实验三 理解make工作的基本原则
    玩转Libmodbus(一) 搭建开发环境
    RT-Thread的C语言多态风格展示
    C++函数默认参数 详解
    杂类-边学边记
  • 原文地址:https://www.cnblogs.com/cfox/p/2984610.html
Copyright © 2011-2022 走看看