我是C編程中的套接字編程的新手,我想編寫一個服務器 - 客戶機原型,其中服務器將充當多個用戶的文件託管服務器(使用TCP協議)。由於服務器和客戶端都需要能夠從stdin中獲取命令,因此我使用了select()函數。這是我的程序的兩個部分的代碼,問題如下:
由於服務器和客戶端都需要能夠從stdin接收命令並處理它們,並且服務器必須發送響應客戶端的請求,程序在某個點阻塞,服務器只有在客戶端發送了另一個請求後才發送它的響應。我認爲這是由於在server.c文件中同時使用了send()和recv(),但我不完全確定。服務器/客戶端模型塊I/O複用
server.c
while(1) {
if (select(maxfd+1,&tmpfds,NULL,NULL,NULL) == -1) {
error("Err in select");
}
for(i = 0; i < maxfd; i++) {
if(FD_ISSET(i,&tmpfds) {
if (i == listenfd) {
< add new client to list >
}
else if (i == 0) { /* keyboard input */
< parse server commands >
}
else {
/* This is where I think my problem is*/
recv(i,buffer,BUFLEN,0);
process(buffer);
send(i,buffer,BUFLEN,0);
}
}
}
client.c
while(1) {
if(select(fdmax+1,&tmpfds,NULL,NULL,NULL) == -1) {
error("Err in select");
}
if (FD_ISSET(0,&tmpfds)) {
fgets(buffer,BUFLEN,stdin);
process_request(buffer);
send(serverfd,buffer,BUFLEN,0);
}
else if (FD_ISSET(serverfd,&tmpfds)) {
recv(serverfd,buffer,BUFLEN,0);
process_response(buffer);
}
}
另外,還請我的編碼風格或C的習慣沒有苛刻的評論。我在任何情況下都不是C專家,也不是我自稱的,我只是在學習,所以請幫助我。我做錯了什麼,如何在不改變(太多)我的程序行爲的情況下避免這種情況?
默認情況下,請記住'recv'無限期地阻止。你可以用'setsockopt'設置超時時間。 – chrisd1100
另外,你需要管理循環內的'fd_set'數據,你不需要注意,Linux的['select'教程](http://linux.die.net/man/2/select_tut)指出:「由於select()修改了它的文件描述符集合,因此如果在循環中使用該調用,那麼在每次調用之前必須重新初始化這些集合。」 – Myst
P.S.如果使用linux,比'select'更喜歡'epoll'。如果使用BSD,比'select'更喜歡'kqueue'。 Windows有重疊IO,Solaris有'evpoll' ...考慮使用抽象庫(即'libev'),如果你的代碼需要在不同的系統上運行......祝你好運! – Myst