C++ 在同时运行多个连接时,我会强烈建议您在考虑边缘触发之前掌握级别触发的使用。即使这样,我也不会费心,我确实删除了accept循环,因为它看起来很愚蠢;甚至不知道这个例子为什么会有这样的结果。(我知道,为什么,这也很愚蠢。)不幸的是,再加上移除边缘触发并立即调
C++ 在同时运行多个连接时,我会强烈建议您在考虑边缘触发之前掌握级别触发的使用。即使这样,我也不会费心,我确实删除了accept循环,因为它看起来很愚蠢;甚至不知道这个例子为什么会有这样的结果。(我知道,为什么,这也很愚蠢。)不幸的是,再加上移除边缘触发并立即调,c++,sockets,epoll,C++,Sockets,Epoll,在同时运行多个连接时,我会强烈建议您在考虑边缘触发之前掌握级别触发的使用。即使这样,我也不会费心,我确实删除了accept循环,因为它看起来很愚蠢;甚至不知道这个例子为什么会有这样的结果。(我知道,为什么,这也很愚蠢。)不幸的是,再加上移除边缘触发并立即调用我的接收函数,并没有影响结果。@DigitalMan-我刚刚更新了这个答案(因为我点击了“post”太快了。请再读一遍。在任何情况下,我都在使用我自己的TCP套接字应用程序中的ePoLo,我只是在前几天工作。当我看到我的代码有同样的bug时,
在同时运行多个连接时,我会强烈建议您在考虑边缘触发之前掌握级别触发的使用。即使这样,我也不会费心,我确实删除了accept循环,因为它看起来很愚蠢;甚至不知道这个例子为什么会有这样的结果。(我知道,为什么,这也很愚蠢。)不幸的是,再加上移除边缘触发并立即调用我的接收函数,并没有影响结果。@DigitalMan-我刚刚更新了这个答案(因为我点击了“post”太快了。请再读一遍。在任何情况下,我都在使用我自己的TCP套接字应用程序中的ePoLo,我只是在前几天工作。当我看到我的代码有同样的bug时,我有点恐慌。但是,它似乎处理好多个连接。在这种情况下,通信需要保持同步。它是同步的,因此它会立即发送,而不是冒着某些东西妨碍或发送顺序错误的风险。它被设置为记录发送错误,到目前为止从未记录过。我删除了accept循环,因为这只是“更好”如果它在同一纳秒内接收到两个连接,我对此表示怀疑。但是,已经发现,删除边缘触发确实会导致处理按预期来回反弹。一个客户端仍然挂起,但现在问题应该更加孤立。@DigitalMan-如果通信需要保持同步,那么为什么要同时处理多个连接呢?1)epoll最初是为边缘触发使用而设计的,我完全理解它的工作原理,因为它很有意义。2,3,4,已经完成了,因为这也是有意义的。到目前为止,发送从未失败或碰到过eWolfBlock-如果失败,我将设计一些系统来处理它,但在它发生之前我不会这么做。欢迎您将其用作边缘触发设备,只是不要指定
ePllet
标志。它仍然会在每一个边缘触发。如果你错过了一个信号,它不会死掉。在你关闭它之前,先从epoll
集合中取出插座。为什么?我看不出有什么区别,遇到错误时总是尽快关闭/关闭套接字。@Zind:关闭套接字不会将其从epoll
集中删除,关闭它只会在关闭最后一个引用时将其删除。@DavidSchwartz:(1)关闭/关闭套接字。(2) 从epoll
集合中卸下插座。我执行这两个操作,我想你的意思是这两个操作的顺序很重要。哦,该死,你说得对!天哪,我真是个白痴。我修好了,它运行得很好!好的一面是,至少我的边缘触发实现在整个过程中都是正确的。
#define EVENTMODE (EPOLLIN | EPOLLET | EPOLLRDHUP | EPOLLHUP)
#define ERRCHECK (EPOLLERR | EPOLLHUP | EPOLLRDHUP)
//Setup event buffer:
struct epoll_event* events = (epoll_event*)calloc(maxEventCount, sizeof(event));
//Setup done, main processing loop:
int iter, eventCount;
while (1) {
//Wait for events indefinitely:
eventCount = epoll_wait(pollID, events, maxEventCount, -1);
if (eventCount < 0) {
syslog(LOG_ERR, "Poll checking error, continuing...");
continue;
}
for (iter = 0; iter<eventCount; ++iter) {
int currFD = events[iter].data.fd;
cout << "Working with " << events[iter].data.fd << endl;
if (events[iter].events & ERRCHECK) {
//Error or hangup:
cout << "Closing " << events[iter].data.fd << endl;
close(events[iter].data.fd);
continue;
} else if (!(events[iter].events & EPOLLIN)) {
//Data not really ready?
cout << "Not ready on " << events[iter].data.fd << endl;
continue;
} else if (events[iter].data.fd == socketID) {
//Event on the listening socket, incoming connections:
cout << "Connecting on " << events[iter].data.fd << endl;
//Set up accepting socket descriptor:
int acceptID = accept(socketID, NULL, NULL);
if (acceptID == -1) {
//Error:
if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
//NOT just letting us know there's nothing new:
syslog(LOG_ERR, "Can't accept on socket: %s", strerror(errno));
}
continue;
}
//Set non-blocking:
if (setNonBlocking(acceptID) < 0) {
//Error:
syslog(LOG_ERR, "Can't set accepting socket non-blocking: %s", strerror(errno));
close(acceptID);
continue;
}
cout << "Listening on " << acceptID << endl;
//Add event listener:
event.data.fd = acceptID;
event.events = EVENTMODE;
if (epoll_ctl(pollID, EPOLL_CTL_ADD, acceptID, &event) < 0) {
//Error adding event:
syslog(LOG_ERR, "Can't edit epoll: %s", strerror(errno));
close(acceptID);
continue;
}
} else {
//Data on accepting socket waiting to be read:
cout << "Receive attempt on " << event.data.fd << endl;
cout << "Supposed to be " << currFD << endl;
if (receive(event.data.fd) == false) {
sendOut(event.data.fd, streamFalse);
}
}
}
}
bool receive(int socketID)
{
short recLen = 0;
char buff[BUFFERSIZE];
FixedByteStream received;
short fullSize = 0;
short diff = 0;
short iter = 0;
short recSoFar = 0;
//Loop through received buffer:
while ((recLen = read(socketID, buff, BUFFERSIZE)) > 0) {
cout << "Receiving on " << socketID << endl;
if (fullSize == 0) {
//We don't know the size yet, that's the first two bytes:
fullSize = ntohs(*(uint16_t*)&buff[0]);
if (fullSize < 4 || recLen < 4) {
//Something went wrong:
syslog(LOG_ERR, "Received nothing.");
return false;
}
received = FixedByteStream(fullSize);
}
diff = fullSize - recSoFar;
if (diff > recLen) {
//More than received bytes left, get them all:
for (iter=0; iter<recLen; ++iter) {
received[recSoFar++] = buff[iter];
}
} else {
//Less than or equal to received bytes left, get only what we need:
for (iter=0; iter<diff; ++iter) {
received[recSoFar++] = buff[iter];
}
}
}
if (recLen < 0 && errno == EWOULDBLOCK) {
cout << "Would block on " << socketID << endl;
}
if (recLen < 0 && errno != EWOULDBLOCK) {
//Had an error:
cout << "Error on " << socketID << endl;
syslog(LOG_ERR, "Connection receive error: %s", strerror(errno));
return false;
} else if (recLen == 0) {
//Nothing received at all?
cout << "Received nothing on " << socketID << endl;
return true;
}
if (fullSize == 0) {
return true;
}
//Store response, since it needs to be passed as a reference:
FixedByteStream response = process(received);
//Send response:
sendOut(socketID, response);
return true;
}
bool sendOut(int socketID, FixedByteStream &output)
{
cout << "Sending on " << socketID << endl;
//Send to socket:
if (write(socketID, (char*)output, output.getLength()) < 0) {
syslog(LOG_ERR, "Connection send error: %s", strerror(errno));
return false;
}
return true;
}