前幾天在看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,。日誌
若是我將加入的syslog註釋掉,就一切正常,因此我懷疑是使用syslog和syslogd進程在進行UDP通信傳輸日誌時,干擾了accept從而致使後者失敗。code
可是這個過程具體是怎樣的,目前還不得而知,只知道我用的端口是4201,改用其它端口也是這樣。blog
我嘗試過在失敗後重啓accept操做,結果陷入無窮循環,每次都得相同的錯誤。
後記:
後來使用UDP嘗試,發現若是不加syslog則一切正常;若是加了syslog,則recvfrom會阻塞卡死,不接收任何數據。