在调用 recv() 之前检查错误
Checking for errors before recv() called
In遇到了以下问题:
我创建了一个能够使用 select() 处理多个连接的服务器。但是 select 也会返回一个客户端(索引为 FD_SET),如果套接字刚刚收到"客户端断开连接"之类的错误。
是否可以在不调用 recv() 的情况下检查套接字。因为要接收,我需要从我的"缓冲池"中获取缓冲区
示例代码:
int ret = recv(client, buffer_pool->get(), BUFFER_SIZE, 0);
if(ret == -1) ... // something went wrong
好吧,我必须再次释放缓冲区,这几乎浪费了我的池中的一个缓冲区。(短时间)
那么在不调用 recv() 的情况下检查套接字是不可能的吗?
我不确定Windows,但是使用getsockopt()
就像在符合POSIX的系统上的魅力一样。尽管在使用它之前 - 请确保从池中获取缓冲区比进行额外的系统调用更昂贵。下面是一个代码片段:
int my_get_socket_error(int fd)
{
int err_code;
socklen_t len = sizeof(err_code);
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err_code, &len) != 0)
err_code = errno;
else
errno = err_code;
return err_code;
}
更新:
根据此文档,Windows似乎也支持它。
不,没有办法避免recv()
调用。如果select()
报告套接字是可读的,则必须从套接字读取以确定其新状态。如果客户端正常断开连接,recv()
将返回 0,而不是 -1。如果不想浪费池缓冲区,则必须首先读取临时本地缓冲区,然后如果recv()
返回任何数据,则可以检索池缓冲区并将读取的数据复制到其中。
调用 recv 和类似函数不能直接与网络设备或类似设备一起使用。当您发送或接收数据时,您要做的就是询问操作系统的可用数据,或者将数据放入队列中以供发送。然后,当您的代码已经更进一步时,操作系统将完成其他工作。这就是为什么您在下次调用将"接触"操作系统网络层的套接字函数后收到错误的原因。
在这一点上出现错误是正常的,你必须处理它们。
但是为了防止阻塞套接字和浪费缓冲区,请查看实现或就绪库的在线技术,这些技术为您提供了异步使用套接字的方式,这样您就不需要在套接字触发接收回调函数之前定义任何东西,您必须在其中进行实际接收。
同样,一次性接收大量数据也不是好技术,因为您将面临通过TCP层合并或分解数据的问题,因为它是基于流的层。建议在数据包(几个字节)中包含标头并接收它们,这样您就不需要拉取标头,但只有在标头之后,您才希望根据标头中提供的长度读取消息的其余部分。这只是可能的例子。
经过几分钟的工作和您的帮助,我只收到 1 字节,然后收到全额:
SOCKET client = ...;
char temp = 0x00;
int len = recv(client, &temp, 1, 0);
if(len == 0)
{
// .. client error handling
return;
}
char* buffer = m_memory_pool->Get();
len = recv(client, buffer + 1, m_memory_pool->buffer_size() - 1, 0);
buffer[0] = temp;
// data handling
我也尝试为 recv() 设置超时,但似乎在 Windows 下它不起作用,这是我的代码:
...
long timeout_ms = 10;
struct timeval interval = {timeout_ms / 1000, (timeout_ms % 1000) * 1000};
if (interval.tv_sec < 0 || (interval.tv_sec == 0 && interval.tv_usec <= 0))
{
interval.tv_sec = 0;
interval.tv_usec = 10000;
}
setsockopt(s_sktIx, SOL_SOCKET, SO_RCVTIMEO, (char *)&interval, sizeof(struct timeval));
...
- error_code:如何设置和检查错误
- CocoaPod - 在头文件中使用 C++ 时出现 Podspec 检查错误
- 在编写包装现有函数并检查错误的模板函数时,如何使用完美转发?
- swscanf_s - 运行时检查错误
- 为什么C++字符串迭代器不检查错误?
- 如何使用运行时检查错误来修复我的C 格斗游戏
- XCode -Mac App -Bootstrap启动时检查错误
- 挂钩发送/WSASEND返回运行时检查错误#0
- 从整数到枚举值时,如何和何处检查错误
- C .如何检查错误的输入
- C++ 输入字符而不是 int 会导致无限循环.如何检查错误的输入
- 检查错误时重载>>运算符中的无限循环
- 开发基本的C++代码+检查错误/警告
- 在C++中,如何在使用gzstream编写压缩文件时检查错误
- 如何使 cuda-memcheck 在出现泄漏检查错误时返回非零
- 是否可以使用GetLastError检查错误代码是否已恢复
- 何时检查错误,使用 QIODevice 的阻塞接口(QTcpSocket 和 QFile)
- 在调用 recv() 之前检查错误
- C++类型检查错误
- 如何修复配置 PHP 7.0.1 时C++预处理器"/lib/cpp"健全性检查错误