Unix/Linux socket 編程的一個問題?

服務端提供一個返回時間的服務,客戶端使用telnet去訪問

#include &
#include &
#include &
#include &
#include &
#include &
#include &
#include &
#include &

#define PORTNUM 13000
#define HOSTLEN 256
#define oops(msg) {perror(msg); exit(1);}

int main()
{
struct sockaddr_in saddr;
struct hostent *hp;
char hostname[HOSTLEN];
int sock_id, sock_fd;
FILE *sock_fp;
char *ctime();
time_t thetime;

sock_id = socket(PF_INET, SOCK_STREAM, 0);
if( sock_id == -1 )
oops("scoket");

bzero((void*)saddr, sizeof(saddr));

gethostname(hostname, HOSTLEN);
hp = gethostbyname(hostname);

bcopy((void*)hp-&>h_addr, (void*)saddr.sin_addr, hp-&>h_length);
saddr.sin_port = htons(PORTNUM);
saddr.sin_family = AF_INET;

if( bind(sock_id, (struct sockaddr*)saddr, sizeof(saddr)) != 0 )
oops("bind");

if( listen(sock_id, 1) != 0 )
oops("listen");

while(1) {
sock_fd = accept(sock_id, NULL, NULL);
printf("Wow! got a call
");
if( sock_fd == -1 )
oops("accept");

sock_fp = fdopen(sock_id, "w");
if (sock_fp == NULL)
oops("fdopen");
thetime = time(NULL);

fprintf(sock_fp, "The time here is...");
fprintf(sock_fp, "%s", ctime(thetime));
fclose(sock_fp);
}
}

運行結果如下:

deweixudeMBP:socket deweixu$ ./timeserv.out
[1] 32999
deweixudeMBP:socket deweixu$ hostname
deweixudeMBP.lan
deweixudeMBP:socket deweixu$ telnet deweixudeMBP.lan 13000
Trying 192.168.199.205...
Wow! got a call
Connected to deweixudembp.lan.
Escape character is "^]".
Wow! got a call
accept: Bad file descriptor
Connection closed by foreign host.
[1]+ Exit 1 ./timeserv.out
deweixudeMBP:socket deweixu$

為什麼會 `accept: Bad file descriptor` ?


sock_fp = fdopen(sock_id, "w");

改成

sock_fp = fdopen(sock_fd, "w");

話說如果變數命名的時候Hamming距離大一點就不會犯這種錯誤了,比如 sock_id 改成 listening_fd。


fclose(sock_fp);

一般來說,bad file descriptor會有兩種情況。一個是用的時候被其他地方關閉了,另外一種是錯誤的值。


感覺代碼有點辣眼睛啊!

fdopen(sock_id) 只是返回了文件指針而已,並不會增加 socket 的引用計數,你後面 fclose 了 sock_fp 就相當於關閉了監聽 socket ,再 accept 肯定返回錯誤啊!


推薦閱讀:

如何系統學習有限元技術?
你編程的動力是什麼?
有沒有程序大牛想過寫本外行看的編程教程?

TAG:編程 | C編程語言 | UNIX環境高級編程書籍 |