我是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