首页 > 解决方案 > 如何用winsock正确recv?

问题描述

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

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

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

标签: c++winsock

解决方案


首先,在读取 HTTP 请求时应该遵循 HTTP 协议:

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

为了处理可能行为不端的客户端,在使用阻塞套接字时,习惯上在发出recvsend调用之前设置套接字超时。

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

当 arecvsend超时时,它将失败并WSAGetLastError给出WSAETIMEDOUT(10060)。


推荐阅读