[apue] syslog 致使 accept 出错?

前几天在看apue第16章关于socket的例子,就是一个很是典型的socket服务器,关键代码以下:git

void serve (int sockfd)
{
    int ret; 
    int clfd; 
    int status; 

    FILE *fp; 
    pid_t pid; 
    char buf[BUFLEN]; 

    for (;;) { 
        clfd = accept (sockfd, NULL, NULL); 
        if (clfd < 0) { 
            syslog (LOG_ERR, "accept error: %d, %s", errno, strerror (errno)); 
            //if (errno == EOPNOTSUPP)
            //{
            //    syslog (LOG_INFO, "retry.."); 
            //    continue; 
            //}

            exit (1); 
        }

        fp = popen ("/usr/bin/uptime", "r"); 
        if (fp == NULL) { 
            sprintf (buf, "error: %s\n", strerror (errno)); 
            ret = send (clfd, buf, strlen (buf), 0); 
            syslog (LOG_ERR, "write back %d for error", ret); 
        } else { 
            while (fgets (buf, BUFLEN, fp) != NULL) 
            {
                ret = send (clfd, buf, strlen (buf), 0); 
                // very amazing, add these log will lead to accept failed with EOPNOTSUPP (95)
                // maybe syslog used dgram socket confuse us..
                syslog (LOG_ERR, "write back %d", ret); 
            }

            pclose (fp); 
        }

        close (clfd); 
    }
}

当accept成功返回一个链接clfd后,使用这个serve方法来服务客户端的请求,简单说就是经过popen启动uptime命令返回当前系统运行时长,而后将uptime的输出导出到clfd上返回给客户端。github

正常的输出以下:bash

[yunhai@localhost 16.chapter]$ ./uptime_tcp_clt
connect ok
 02:02:26 up 6 days,  4:40,  5 users,  load average: 0.00, 0.00, 0.00

 可是与书上例子不一样,为了查看服务端的活动状况,我在serve中加了几句syslog输出,以便经过  tail -f /var/log/messages 来查看服务运行的状况。服务器

正常状况下服务输出以下:socket

ruptimed: write back 70

 可是神奇的事情发生了,我再次启动客户端后,连不上服务器了:tcp

[yunhai@localhost 16.chapter]$ ./uptime_tcp_clt
connect failed, retry...
connect failed, retry...
connect failed, retry...

 再看服务器进程,竟然已经退出了,回来查看daemon日志,发现这么一句:spa

ruptimed: accept error: 95, Operation not supported

 原来accept出错致使服务器退出了,错误码是95,EOPNOTSUPP日志

若是我将加入的syslog注释掉,就一切正常,因此我怀疑是使用syslog和syslogd进程在进行UDP通信传输日志时,干扰了accept从而致使后者失败。code

可是这个过程具体是怎样的,目前还不得而知,只知道我用的端口是4201,改用其它端口也是这样。blog

我尝试过在失败后重启accept操做,结果陷入无穷循环,每次都得相同的错误。

 

服务端代码

客户端代码

 

后记:

后来使用UDP尝试,发现若是不加syslog则一切正常;若是加了syslog,则recvfrom会阻塞卡死,不接收任何数据。

相关文章
相关标签/搜索