select()无法处理大量数据

select()无法处理大量数据,select,winsock,Select,Winsock,因此,我在代码中使用TerminateThread作为recv函数正确超时的替代品,这让我感到羞耻。我刚刚实现了select,这是出于良好的实践,但它似乎无法处理接收数据所需的大小和速度 DWORD WINAPI recv_low(LPVOID randparam) { fd_set fd; timeval timeout; FD_ZERO(&fd); FD_SET(UseSocket,&fd); timeout.tv_sec = 5;

因此,我在代码中使用TerminateThread作为recv函数正确超时的替代品,这让我感到羞耻。我刚刚实现了select,这是出于良好的实践,但它似乎无法处理接收数据所需的大小和速度

DWORD WINAPI recv_low(LPVOID randparam) {
    fd_set fd;
    timeval timeout;
    FD_ZERO(&fd);
    FD_SET(UseSocket,&fd);
    timeout.tv_sec = 5;
    timeout.tv_usec = 0;
    int sel = 0;
    iResult2 = 0;
    sel = select (UseSocket+1,&fd,NULL,NULL,&timeout);
    if (sel != 0 ) {
        iResult2 = recv(UseSocket, recvbuf, recvbuflen, 0);
    }
    return 1;
}
这是具有正确超时的接收函数的代码。 对于少量数据,它可以正常工作,但当我启动它并开始接收每秒65535大小的缓冲区时,它完全崩溃,我的程序异常退出,返回代码为0

但是,如果我使用我的旧方法:

DWORD WINAPI recv_low(LPVOID randparam) {
    iResult2 = 0;
    iResult2 = recv(UseSocket, recvbuf, recvbuflen, 0);
    return 1;
}

int main() {
    DWORD dwrecvthreadId;
    HANDLE recvthread = CreateThread(NULL,0,recv_low,NULL,0,&dwrecvthreadId);
    WaitForSingleObject(recvthread, 5000);
    if (iResult2 > 0) //Do stuff
    else if ( iResult2 == 0 ) {
        TerminateThread(recvthread, 0);
    }
}
它如预期的那样完美地工作;它接收数据而不退出

至于为什么会这样,我一点也不知道。我试着往回走,看看代码中还有什么可能导致我的程序以返回代码0退出,但我一直无法找到它真正跳起来并返回的地方。 我不得不相信它与select有关,或者至少与我对它的使用有关

有人有什么建议吗? 是的,我为错误的伪ish代码道歉。我不打算发布我的程序的大得惊人的主要功能


编辑:进一步发展;问题的根源与select有关。我设法发现,当我使用上面设置的select机制发送大缓冲区时,recv不会读取它发送的所有数据。例如,我发送了6条消息,全部包含65530字节,这只是为了更好地测量。然后recv会告诉我它读了多少。第一个缓冲区被读取为12524字节,下一个缓冲区被读取为14952字节,以此类推。这似乎是我问题的基础。

选择返回时!=0,它实际上是返回-1套接字错误,还是返回>0?在这两种情况下,您都在调用recv,但如果select返回-1,则不应调用recv。除此之外,recvbuf在哪里分配,recvbuflen在哪里初始化?UseSocket是在阻塞模式还是非阻塞模式下运行?如果阻塞,另一种选择是使用setsockoptSOL_SOCKET,SO_RCVTIMEO在recv本身上设置阻塞超时。如果代码崩溃,则您正在访问无效内存。你有没有试着用调试器来找出在哪里以及为什么?嗯,它没有崩溃。它回来了。正在返回,代码为0。我一辈子都找不到原因。此处描述为main的函数的父函数甚至没有返回0的控制路径。但是,只有当我使用selectWhat返回0时才会发生这种情况?如果select返回0,则表示超时,这意味着等待的套接字上没有数据。如果recv返回0,则另一方已正常断开套接字连接(假定recvbuflen不是0)。不,实际上我的整个过程都返回0。比如,我的主要功能。奇怪的是,0甚至不是控件路径返回的选项之一-等等,是的。我的错。我设法忽略了返回0;在函数的末尾。但这仍然提出了一个问题,它究竟是如何做到这一点的?接收函数设置在无限循环中;如果接收线程因任何原因死亡,它将自动重新启动。无限循环似乎即将结束,因此我的过程将和平地退出。