【问题标题】:Does BeginReceive() get everything sent by BeginSend()?BeginReceive() 是否获取 BeginSend() 发送的所有内容?
【发布时间】:2010-05-06 09:09:47
【问题描述】:

我正在编写一个同时具有服务器端和客户端的程序,并且客户端将连接到由同一程序托管的服务器(但通过它的另一个实例,通常在另一台机器上)。所以基本上,我可以控制协议的两个方面。

我在两边都使用BeginReceive()BeginSend()来发送和接收数据。我的问题是这两个陈述是否属实:

  1. 使用对 BeginReceive() 的调用将为我提供在调用回调函数时在另一端通过对 BeginSend() 的单个调用发送的全部数据。

  2. 使用对 BeginSend() 的调用会将我传递给另一端的全部数据发送到另一端,而另一端对 BeginReceive() 的单个调用将接收到所有数据。

两者其实基本相同。

如果答案是否定的,根据我所阅读的有关套接字的内容,我猜测是这种情况,那么处理命令的最佳方式是什么?我正在编写一个游戏,它将具有诸如PUT X Y 之类的命令。我正在考虑在每个命令的末尾附加一个特殊字符(例如#),并且每次收到数据时,我都会将其附加到缓冲区中,然后仅在遇到# 后才对其进行解析。

【问题讨论】:

    标签: c# .net sockets asynchronous


    【解决方案1】:

    不,您不能指望BeginReceive 一定会收到来自对BeginSend 的一次调用的所有数据。您可以在一次调用中向BeginSend 发送很多 数据,这些数据很可能被拆分为多个数据包。您可以在单独的接收调用中接收每个数据包的数据。

    将流分成多个块的两种主要方式是:

    • 使用分隔符(根据您当前的建议)。这样做的好处是不需要事先知道大小,但缺点是相对难以解析,并且可能会引入诸如转义分隔符之类的要求。
    • 在每条消息之前添加大小。接收器可以先读取长度,然后准确知道预期的数据量。

    【讨论】:

    • 我就是这么想的。只是为了确保我知道在使用分隔符时如何解析数据:来自两个单独的 BeginSend 调用的数据不能被单个 BeginReceive 调用接收,对吧?例如,如果我做BeginSend("A"), BeginSend("B")BeginReceive 不可能返回“AB”,是吗?那么我是否可以依靠将分隔符作为接收缓冲区中的最后一个字符,而在它之前的所有内容都在某个时候成为单个命令?
    • 跟着我重复; TCP 是字节流。您的发送不是消息。您的接收可以返回从 1 字节到您给它的缓冲区大小的任何地方。没有“消息”。 TCP 是一个字节流。
    • @IVlad:Len 是绝对正确的。不要试图解决 TCP 作为字节流的问题 - 去吧。来自两次 BeginSend 调用的数据绝对可以通过一次 BeginReceive 调用返回。
    猜你喜欢
    • 1970-01-01
    • 2021-06-28
    • 2016-09-30
    • 2017-09-14
    • 1970-01-01
    • 1970-01-01
    • 2021-03-04
    • 2013-01-24
    • 1970-01-01
    相关资源
    最近更新 更多