【问题标题】:Problem using Connect(), send(), recv, with UDP sockets使用带有 UDP 套接字的 Connect()、send()、recv 时出现问题
【发布时间】:2016-06-26 01:04:24
【问题描述】:

对于我的 Uni 任务,我必须创建一个快节奏的网络游戏,因此选择使用 UDP 而不是 TCP。我知道 UDP 和 TCP 编程的许多不同之处,并且通读了 MSDN 关于 winsock 的文档的大部分相关部分。在 MSDN 上,它声明通过 connect() 函数创建 UDP 套接字应该将套接字绑定到指定的地址和端口,因此能够将 send() 和 recv() 函数与创建的套接字一起使用。

对于我的应用程序,我创建了一个客户端并使用环回地址使用 connect(),该环回地址通过 send() 函数发送多个数据包。客户端在调用 select() 之后,会收到它发出的数据包。但是我从 recv() 函数得到的结果是 SOCKET_ERROR 并且使用 WSAGetLastError() 的错误描述是“现有连接被远程主机强行关闭”。

如果我使用bind() 函数并使用sendto() 通过环回地址发送数据,我recv() 数据包没有任何错误...有谁知道为什么connect() 函数没有做它是什么应该这样做,有没有人能够通过 connect() 函数使用 UDP 套接字?

【问题讨论】:

  • UDP 是一种无连接协议。 MSDN 上哪里说要使用 connect()?我想你一定读过一些 TCP 文档......
  • connect() 确实对 UDP 做了一些事情:它设置了 UDP 套接字将向其发送数据包(并从中接收数据包)的地址。这样以后您就可以调用 send() 而不是 sendto()。不是非常有用,真的,但也不是完全没用。
  • @Tony: 不,connect 在无连接套接字上完全有效。它只是将套接字修复为仅允许从单个远程地址发送/接收(因此您可以使用 send 和 recv 而不是 sendto 和 recvfrom)。

标签: c++ c winsock2


【解决方案1】:

如果您希望程序接收 UDP 数据包,则需要调用 bind()。 connect() 仅设置套接字在调用 send() 时将发送数据包的地址;它不会将套接字与要接收的本地 UDP 端口相关联;为此,您必须调用 bind()。

【讨论】:

  • 感谢杰里米,在连接之前调用绑定似乎已经成功了。当我在服务器端编写更多代码时,我会知道更多。
  • 实际调用的是什么,如果你编写的 UDP 服务器只提供一个远程地址,你可以调用 bind() 来绑定服务器端口,它已经将下一个 recv() 调用与该特定端口相关联和IP地址。刚刚测试过。另一方面,在只有 UDP 服务器的 UDP 客户端上,您只需要使用 connect() 到远程地址 - send() 就会知道将数据发送到哪里。
【解决方案2】:

《UNIX 网络编程》指出,在 UDP 客户端套接字上进行的连接调用会预先计算并存储有关目标套接字地址的所有状态(屏蔽、选择接口等),从而节省了执行成本在每个 ::sendto 调用上。这本书声称 ::send 与 ::sendto 相比,可以快 3 倍,因为这减少了开销 - 数据可以绕过大多数 IP 堆栈处理直接进入 NIC 驱动程序。高性能游戏程序员可能需要考虑这一点。

【讨论】:

    【解决方案3】:

    你应该检查Beej's Guide to Network Programming Using Internet Sockets,有很好的例子可以解决你的问题。

    【讨论】:

      【解决方案4】:

      请记住,UDP 协议是“无连接”协议,这意味着您永远不会连接到主机,您只是发送数据。所以你可以看到connect作为一个动作对于UDP是没有意义的。

      对于 UDP,您应该在这些函数中使用 sendto() 和 recvfrom(),您指定地址和缓冲区,仅此而已,在 TCP 中为您轻松处理的所有其他内容都消失了,您必须自己处理.

      在 MSDN 文档中,它提到实际上您可以通过 UDP 以某种方式使用普通的发送/接收功能,但是当您已经拥有单独的功能时,为什么还要这样做呢?就像其他已经评论过的 UDP 的 connect() 所做的其他事情一样,它本质上不是“连接”操作,而是一种设置 send()/recv() 以供 UDP 使用的过滤器。

      【讨论】:

      • 回复:why would you? 键盘懒惰。 :) 对远程主机和端口调用一次connect,然后多次调用send 比不调用connect 和多次调用sendto 需要更少的输入。 :) 不仅仅是函数名的2个字符,还有目标地址的额外参数。
      • connect 可以解释为设置远程对等地址。所以套接字是连接的还是无连接的都没有关系。
      • 请注意,在 UDP 套接字上调用 connect() 的另一个副作用是,从那时起 UDP 套接字将只接收来自您在 connect( ) 称呼;来自其他来源的传入 UDP 数据包将被丢弃。这对你来说是否是个问题取决于你是否想从其他来源接收 UDP 数据包,当然:)
      猜你喜欢
      • 2011-09-05
      • 2016-04-04
      • 1970-01-01
      • 2021-03-20
      • 1970-01-01
      • 2017-09-02
      • 2014-06-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多