c++ - 接收来自服务器的传入流量

标签 c++ windows tcp

我有以下功能设置,每 2 分钟从服务器接收一次数据。我第一次调用该函数时,它似乎可以工作,但随后它在 recv 调用处卡住,并且永远不会返回。即使服务器没有任何内容可发送,我是否需要在每次调用时分配缓冲区?

#define RCVBUFSIZE 32

void Receive()
{   
    UINT totalBytesRcvd = 0, bytesRcvd = 0;
    char buffer[RCVBUFSIZE];     /* Buffer for string */

    /* Receive up to the buffer size (minus 1 to leave space for 
    a null terminator) bytes from the sender */

    bytesRcvd = recv(sockClient, buffer, RCVBUFSIZE - 1, 0);

    if (bytesRcvd)
    {
        buffer[bytesRcvd] = '\0';
        MessageBox(0, buffer, 0, 0); //some way to display the received buffer
    }
    else if (bytesRcvd == SOCKET_ERROR)
    {
        return;
    }
}

最佳答案

(1) 您的缓冲区并未真正分配,它驻留在堆栈上。您通常不必担心在堆栈上使用 32 字节。

(2) recv 应该阻塞,直到有东西要接收。您可以通过使用非阻塞套接字或使用 select 来解决这个问题。请参阅here供引用。

特别是,您可以

(2a) 使用ioctlsocket将套接字设置为非阻塞模式。然后,当您调用 read 并且没有任何内容可读取时,您会收到错误 EWOULDBLOCK

unsigned long non_blocking = 1;
ioctlsocket (sockClient, FIONBIO, &non_blocking);

然后阅读就变成了

bytesRcvd = recv(sockClient, buffer, RCVBUFSIZE - 1, 0);
if (bytesRcvd == -1) {
    if (WSAGetLastError() == EWOULDBLOCK) {
        // nothing to read now
    } else {
        // an actual error occurred
    }
} else {
    // reading was successful. Call to MsgBox here
}

(2b) 或者,您可以调用 select在实际调用read之前确定是否有数据要读取。

struct timeval timeout;
timeout.tv_usec = 0;
timeout.tv_sec = 0;

fd_set r;
FD_ZERO (&r);
FD_SET (sockClient, &r);
switch (select (sockClient + 1, &r, NULL, NULL, &timeout)) {
    case -1:
        // error
        break;
    case 0:
        // nothing to read
        break;
    case 1:
        // you may call read ()
        break;
}

关于c++ - 接收来自服务器的传入流量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4245134/

相关文章:

c++ - 等一下

c# - Windows 服务的数据执行保护

windows - 当用户不使用 "Safely Remove Hardware"时,如何确保文件永久保存在 USB 上?

java - TcpInboundGateway - 读取特定数量的字节

Java维护持久的TCP连接

sockets - 无法使用 boost asio 设置 TCP 源端口

c++ - 反转字符串 C++

c++ - 多值 DWORD 枚举作为一个函数参数 C++

c++ - 如何从通过模板继承的类中提取 typedef 信息?

c - 在winapi中拖放