在调用recv()之前检查错误

问题描述 投票:2回答:5

在得到以下问题:

我创建了一个能够使用select()处理多个连接的服务器。但是如果套接字刚刚出现像“客户端断开连接”之类的错误或者其他什么,那么select也会返回一个客户端(索引为FD_SET)。

是否可以在不调用recv()的情况下检查套接字。因为接收我需要从我的“BufferPool”中获取缓冲区

示例代码:

int ret = recv(client, buffer_pool->get(), BUFFER_SIZE, 0);
if(ret == -1) ... // something went wrong

那么我必须再次释放缓冲区,这几乎浪费了我的池中的一个缓冲区。 (很短的时间)

所以不能在不调用recv()的情况下检查套接字

c++ windows sockets recv
5个回答
3
投票

我不确定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;
}

更新:

根据this document,似乎Windows也支持它。


1
投票

不,没有办法避免recv()电话。如果select()报告套接字是可读的,那么您必须从套接字读取以确定其新状态。如果客户端正常断开连接,recv()将返回0,而不是-1。如果您不想浪费池化缓冲区,则必须首先读入临时本地缓冲区,然后如果recv()返回任何数据,您可以检索池化缓冲区并将读取的数据复制到其中。


0
投票

调用recv和类似功能不能直接与网络设备或类似的东西一起使用。发送或接收数据时,您所做的只是询问操作系统的可用数据,或将数据放入队列进行发送。当你的代码已经进一步发展时,OS将完成另一项工作。这就是为什么在下次调用将“联系”OS网络层的套接字函数后收到错误的原因。

在这一点上获得错误是正常的,你必须处理它们。

但是为了防止阻塞套接字和浪费缓冲区,请查看实现或准备库的在线技术,这些技术为您提供了使用套接字的异步方式,这样您就不需要在套接字触发接收回调函数之前定义任何内容实际接收。

同样,一次接收大量数据并不是一项好技术,因为你将面临通过TCP层合并或拆分数据的问题,因为它是基于流的层。建议在您的数据包中包含标头(几个字节)并接收它们,这样您就不需要拉取标头,但只有在标头之后您才想根据标头中提供的长度读取其余信息。这只是可能的例子。


0
投票

经过几分钟的工作和你的帮助后,我收到1byte才收到全额:

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

0
投票

我也尝试为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));
...
© www.soinside.com 2019 - 2024. All rights reserved.