[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會阻塞卡死,不接收任何數據。

相關文章
相關標籤/搜索