我正在编写一个客户端服务器应用程序,我正在使用poll来在多个客户端套接字和stdin之间进行多路复用,我可以在其中插入命令(例如:停止服务器)。我相信我的代码的结构(“逻辑”)是正确的,但它的行为并不像我期望的那样:
struct pollfd pfd[NSERVER]; //defined as 10
pfd[0].fd = fileno(stdin);
pfd[0].events = POLLIN;
pfd[1].fd = socktfd; //server bind, listen socket
pfd[1].events = POLLIN;
struct sockaddr_storage remoteaddr; // client address
socklen_t addrlen;
char remoteIP[INET6_ADDRSTRLEN];
addrlen = sizeof remoteaddr;
char buf[1024]; // buffer
int pos=2;
while(poll(pfd,1,0) >= 0)
{
if(pfd[0].revents & POLLIN) { //stdin
//process input and perform command
}
if(pfd[1].revents & POLLIN) {
/* new connection */
int connsockfd = accept(socktfd, (struct sockaddr *)&remoteaddr,&addrlen);
pfd[pos].fd=connsockfd;
}
int i=2;
//Loop through the fd in pfd for events
while (i<=NSERVER)
{
if (pfd[i].revents & POLLIN) {
int c=recv(pfd[i].fd, buf, sizeof buf, 0);
if(c<=0) {
if (c==0)
{
/* Client closed socket */
close(pfd[i].fd);
}
}else
{//Client sent some data
c=send(pfd[i].fd,sbuff,z,0);
if (c<=0)
{
Error;
}
free(sbuff);
}
}
i++;
}
}
我删除了recv中的一些代码并发送以使代码更易于阅读。 它无法表现(它只是挂起,不接受连接或对stdin的输入做出反应)。
注意:我更倾向于使用轮询选择,所以请不要指向选择: - )。
提前感谢您的任何帮助。
答案 0 :(得分:3)
pfd[i].fd = -1
,因此最初会被poll()忽略。poll(pfd, 1, 0)
错误,至少应为poll(pfd, 2, 0)
甚至poll(pfd, NSERVER, 0)
。while(i<=NSERVER)
应为while(i<NSERVER)
您的程序可能会挂起,因为您循环遍历pfd数组,该数组未初始化并包含.fd和.revents的随机值,因此它希望在可能阻塞的某个随机FD上发送()或recv()。在if(pdf[i].fd < 0) {i++; continue;}
循环中i<NSERVER
。
您也没有在新接受的套接字上设置pfd[pos].events = POLLIN
。除非您有要发送的内容,否则不要设置POLLOUT
,因为它几乎每次都会触发。