在使用C/C 的异步插座时,检测远程断开(半粘液)
Detect remote disconnect (half-close) when using asynchronous sockets in C/C++
在使用c/c
中使用异步插座时检测远程断开(半连接)我使用以异步模式(fcntl(sock, F_SETFL, O_ASYNC);
)运行的C插座实现了TCP/IP客户端,以最大程度地减少阻止。客户端将仅将数据发送到服务器,并且永远不会收到任何数据。因此,循环看起来像这样:
while (true) {
...
fd_set writefds;
FD_ZERO(&writefds);
FD_SET(socketFd, &writefds);
select(socketFd + 1, NULL, &writefds, NULL, &selectTimeout);
if (FD_ISSET(socketFd, &writefds)) {
ssize_t cBytes = send(socketFd, someBuffer, someSize, 0);
...
}
...
}
如何检测服务器是否断开连接?正如此问题所建议的那样,最初合理的解决方案是调用recv(socketFd, &buf, len, MSG_PEEK);
并检查该调用是否返回0。但是,这显然不起作用,因为首先,服务器实际上并未在我的情况下发送任何数据。其次,在广义的情况下,服务器可能不会一直发送数据,因此recv()
因此会返回0,因为它是非阻滞的。
使用tcpdump监视服务器与客户端之间的连接时,服务器关闭连接时会发送一个鳍数据包,但客户端不承认这一点。我无法使用recv()
,send()
和select()
识别它的半粘液。实际上,第一个迹象表明问题是错误的是服务器发送rst时客户端试图将数据发送到现在关闭的连接时:
IP6 ::1.62179 > ::1.2526: Flags [S], seq ..., length 0
IP6 ::1.2526 > ::1.62179: Flags [S.], seq ..., length 0
IP6 ::1.62179 > ::1.2526: Flags [.], ack 1, ..., length 0
IP6 ::1.2526 > ::1.62179: Flags [.], ack 1, ..., length 0
IP6 ::1.2526 > ::1.62179: Flags [F.], seq 1, ..., length 0
IP6 ::1.62179 > ::1.2526: Flags [.], ack 2, ..., length 0
IP6 ::1.2526 > ::1.62179: Flags [.], ack 1, ..., length 0
IP6 ::1.62179 > ::1.2526: Flags [P.], seq 1:7, ack 2, ..., length 6
IP6 ::1.2526 > ::1.62179: Flags [R], seq ..., length 0
如何确定服务器已经发送了鳍数据包,以便在尝试发送下一个数据包之前可以清洁关闭所有内容?
解决此问题的解决方案是使用sys/poll.h
中定义的poll()
。poll()
如果在插座上收到鳍片,将在pollfd
结构中设置POLLHUP
位:
#include <sys/poll.h>
...
pollfd ufds[1];
ufds[0].fd = socketFd;
ufds[0].events = POLLIN;
int pollRes = poll(ufds, 1, 0);
if (pollRes == 1) {
if (ufds[0].revents & POLLHUP) {
std::cout << "Got FIN, closing socket." << std::endl;
shutdown(socketFd, SHUT_RDWR);
close(socketFd);
...
}
}
服务器可能不会始终发送数据,因此Recv()因此将返回0,因为它是非阻滞的。
否。如果您在活动连接上调用它,则recv
将不会返回0。如果发生错误,它将返回读取或-1的字节数(检查errno)。它仅在同行执行有序关闭检查的男人页面
如何确定服务器已经发送了鳍数据包,以便在尝试发送下一个数据包之前可以清洁关闭所有内容?
您的代码应执行recv
,确定下一个操作的返回值。返回0表示对等方已关闭连接。
- 从不同线程使用int64的不同字节安全吗
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- 在C++中使用cURL和多线程
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 在cuda线程之间共享大量常量数据
- 当套接字连接断开时检测C/C++Unix
- 如何将元素添加到数组的线程安全函数?
- 线程,如果else语句,都是错误的上下文切换后,会发生什么
- C++Boost Asio Pool线程,带有lambda函数和传递引用变量
- Qt C++静态thread_local QNetworkAccessManager是线程应用程序的好选择吗
- 异常属于C++中的线程还是进程
- C++中的线程安全删除
- C++使用params创建线程函数会导致转换错误
- 尝试通过OCI例程从Oracle获取blob数据,但出现错误:ORA-01008:并非所有变量都绑定
- 类与私有变量的其他类之间的线程安全性
- CoInitialize()在单独的线程上崩溃而不返回
- c++类声明时,相同的例程,不同的成员变量类型
- 视频在唤醒其他线程时输入设备断开连接
- 在使用C/C 的异步插座时,检测远程断开(半粘液)
- 处理客户端断开连接后服务器应用程序中的线程