2

我正在使用 UDP 编写一个简单的 Web 服务器和客户端,到目前为止:

  • 程序可以相互连接,
  • 客户端可以发送请求,
  • 服务器可以读取请求,
  • 服务器可以识别客户端的IP地址和客户端的端口,并且
  • 服务器可以将消息发送回客户端

我的问题是我的客户端代码卡在rcvfrom函数中等待,即使在服务器发送响应之后也是如此。

这是应该获取服务器消息并返回套接字读取的字节数的函数:

ssize_t receive_from_server(rdp_socket *rsocket, char *buffer, size_t buf_len){

  socklen_t sendsize = sizeof(rsocket->server_addr);
  bzero(&(rsocket->server_addr), sendsize);
  //STUCK HERE:
  return recvfrom(rsocket->sockfd, buffer, buf_len, 0,           
       (struct sockaddr*)&(rsocket->server_addr), &sendsize);
}

我为两者设置了 sockoptsSO_SNDTIMEOSO_RCVTIMEO在几秒钟后超时。

问题:

在短期内,我将添加确认 (ACK) 以实现可靠的数据传输。我想丢失 ACK 可能是问题所在,但我只是想知道,对于受过训练的眼睛来说,这是否是一个不同的问题。

超时工作是否需要 ACK?

如何同步我的客户端和服务器,以便它们能够真正相互通信?

4

1 回答 1

2

由于 UDP 不提供可靠性,您将需要实现丢失数据的重传。由于看起来这是一个客户端请求服务器响应模型,所以对您来说最简单的重传实现可能是在等待响应超时时重新发送请求,然后再次等待响应。您可能希望实现重试计数器并在重试一定次数后放弃。

如果SO_RCVTIMEOSO_SNDTIMEO套接字选项似乎没有生效,则可能是这些选项没有针对该类型的套接字实现。检查调用的返回值setsockopt()以确保它们成功。

作为一种解决方法,您可以更改receive_from_server()函数以使用poll()select()等待可读事件一段时间,而不是阻塞在recvfrom().

ssize_t receive_from_server(rdp_socket *rsocket, char *buffer, size_t buf_len){
  struct pollfd pfd = { rsocket->sockfd, POLLIN };
  int pollresult = poll(&pfd, 1, RECV_TIMEOUT_SECONDS * 1000);

  if (pollresult > 0) {
    socklen_t sendsize = sizeof(rsocket->server_addr);
    bzero(&(rsocket->server_addr), sendsize);

    return recvfrom(rsocket->sockfd, buffer, buf_len, MSG_DONTWAIT,           
      (struct sockaddr*)&(rsocket->server_addr), &sendsize);
  }

  if (pollresult == 0) {
      errno = ETIME;
  }

  return -1;
}
于 2013-07-31T19:04:35.647 回答