如何使用 winsock 正确接收?

问题描述

我正在为测试编写一个简单的 http 服务器,但我对如何判断请求的结束位置感到很困惑。

recv() 出错时返回负数,连接关闭时返回 0,接收数据时返回正数,当没有更多数据时,它只是阻塞。

我可以创建一些科学怪人,它在一个线程上不断接收数据并检查它是否在另一个线程上阻塞,但必须有更好的方法来做到这一点......我如何判断是否没有更多字节可供读取暂时没有阻塞?

解决方法

首先,读取HTTP请求时要遵循HTTP协议:

  1. 继续从套接字读取直到收到 \r\n\r\n
  2. 解析标题
  3. 如果指定了 Content-Length,则额外读取请求负载的那么多字节
  4. 处理 HTTP 请求
  5. 发送 HTTP 响应
  6. 关闭套接字 (HTTP/1.0) 或 (HTTP/1.1) 句柄保持活动、内容编码、传输编码、预告片等,可能从步骤 1 开始重复。

为了处理潜在的行为不端的客户端,在使用阻塞套接字时,通常会在发出 recvsend 调用之前设置套接字超时。

DWORD recvTimeoutMs = 20000;
setsockopt(socket,SOL_SOCKET,SO_SNDTIMEO,(const char *)&recvTimeoutMs,sizeof(recvTimeoutMs));
DWORD sendTimeoutMs = 30000;
setsockopt(socket,SO_RCVTIMEO,(const char *)&sendTimeoutMs,sizeof(sendTimeoutMs));

recvsend 超时时,它将失败,WSAGetLastError 给出 WSAETIMEDOUT (10060)。