Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/294.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用消息结尾字符获取TCP消息中的所有数据?_C#_.net_Sockets_Tcpclient - Fatal编程技术网

C# 如何使用消息结尾字符获取TCP消息中的所有数据?

C# 如何使用消息结尾字符获取TCP消息中的所有数据?,c#,.net,sockets,tcpclient,C#,.net,Sockets,Tcpclient,我有一个TCP客户机/服务器应用程序,它在本地机器上运行得很好。然而,当我在另一台机器上使用客户机时,只传递了小消息(最多20-30字节)。客户端需要读取更大数据的那一分钟将被锁定。我认为问题在于客户端没有接收到在一个tcp数据包中发送的所有数据。换句话说,我只调用了tcpClient.Client.Receive(tcpBuffer),并假设tcpBuffer拥有它在本地机器上所做的所有数据。现在,服务器发送的消息都以消息中唯一的字节(0xFD)终止。我不知道如何处理这件事。因此,一个问题是,

我有一个TCP客户机/服务器应用程序,它在本地机器上运行得很好。然而,当我在另一台机器上使用客户机时,只传递了小消息(最多20-30字节)。客户端需要读取更大数据的那一分钟将被锁定。我认为问题在于客户端没有接收到在一个tcp数据包中发送的所有数据。换句话说,我只调用了tcpClient.Client.Receive(tcpBuffer),并假设tcpBuffer拥有它在本地机器上所做的所有数据。现在,服务器发送的消息都以消息中唯一的字节(0xFD)终止。我不知道如何处理这件事。因此,一个问题是,NetworkStream.DataAvailable是否提供了客户端或服务器上可用的数据?在得到0xFD值之前,是否必须继续读取和循环?如何才能有效地做到这一点? 因此,基本上我想用如下内容替换tcpClient.Client.Receive(tcpBuffer):

private static byte[] GetTcpResponse()
{
    int arrayLength = tcpClient.Client.Receive(tcpBuffer);
    if (tcpBuffer[arrayLength - 1] == 0xFD)
    {
       return tcpBuffer;
    }
    else
    {
        //this is where I am hung up
    }
}
因此,我挂断的位置可以从上面看出来。我只是做另一个接收吗?如果还没有数据呢? 谢谢,Tom

TCP是基于流的协议,而不是基于数据报的协议。您不应该依赖于具有给定大小的接收数据报,或者您的数据位于任何给定的数据报边界上;您也不应该期望在一个数据报(或任何给定数量的数据报)上接收所有数据。所以当你说:

在得到0xFD值之前,是否必须继续读取和循环

是的,这就是重点但是添加一个合理的超时和适当的异常检查,以便在连接失败时应用程序不会挂起,并且永远不会得到终止值

您的代码可以是这样的(除了超时、错误检查等);我还没有测试过它,但它应该可以帮助您了解:

private static byte[] GetTcpResponse()
{
    var data = new List<byte>();
    var buffer = new byte[512]; //size can be different, just an example
    var terminatorReceived = false;
    while(!terminatorReceived)
    {
        var bytesReceived = tcpClient.Client.Receive(buffer);
        if(bytesReceived > 0)
        {
            data.AddRange(buffer.Take(bytesReceived));
            terminatorReceived = data.Contains(0xFD);
        }
    }
    return data.ToArray();
}
private静态字节[]gettcresponse()
{
var data=新列表();
var buffer=new byte[512];//大小可以不同,仅举一个例子
var terminatorReceived=假;
而(!终止或接收)
{
var bytesserved=tcpClient.Client.Receive(缓冲区);
如果(接收字节数>0)
{
data.AddRange(buffer.Take(bytesReceived));
terminatorReceived=data.Contains(0xFD);
}
}
返回data.ToArray();
}
TCP是基于流的协议,而不是基于数据报的协议。您不应该依赖于具有给定大小的接收数据报,或者您的数据位于任何给定的数据报边界上;您也不应该期望在一个数据报(或任何给定数量的数据报)上接收所有数据。所以当你说:

在得到0xFD值之前,是否必须继续读取和循环

是的,这就是重点但是添加一个合理的超时和适当的异常检查,以便在连接失败时应用程序不会挂起,并且永远不会得到终止值

您的代码可以是这样的(除了超时、错误检查等);我还没有测试过它,但它应该可以帮助您了解:

private static byte[] GetTcpResponse()
{
    var data = new List<byte>();
    var buffer = new byte[512]; //size can be different, just an example
    var terminatorReceived = false;
    while(!terminatorReceived)
    {
        var bytesReceived = tcpClient.Client.Receive(buffer);
        if(bytesReceived > 0)
        {
            data.AddRange(buffer.Take(bytesReceived));
            terminatorReceived = data.Contains(0xFD);
        }
    }
    return data.ToArray();
}
private静态字节[]gettcresponse()
{
var data=新列表();
var buffer=new byte[512];//大小可以不同,仅举一个例子
var terminatorReceived=假;
而(!终止或接收)
{
var bytesserved=tcpClient.Client.Receive(缓冲区);
如果(接收字节数>0)
{
data.AddRange(buffer.Take(bytesReceived));
terminatorReceived=data.Contains(0xFD);
}
}
返回data.ToArray();
}

有趣的故事:我曾经写过一个桌面应用程序,它可以显示来自网络摄像头的照片,我将许多照片切成两半。事实证明,驱动程序错误地假设所有照片数据在请求时都已被接收(通过TCP流),但通常只有部分数据可用。我必须安装一个网络嗅探器,对摄像头发送的数据结构进行反向工程,并使用此答案中提供的策略编写自己的驱动程序。嗨,是的,我确实看到了你的摄像头故事。我尝试了一些事情,但没有成功,但我会尝试这个。这整件事让我很扫兴,因为它在同一台机器上都很成功,但当它在不同的机器上运行时,就无法处理更大的数据消息。UDP的一切都很好,但我需要消息对消息的可靠性。谢谢如果基于数据报的方法更适合您的项目,那么UDP是一个不错的选择,但是您需要添加一个控制机制来处理丢失和无序的数据报。例如,这正是服务器所需要的。我觉得更难,因为它是异步的。有趣的故事:我曾经写过一个桌面应用程序,它可以显示来自网络摄像机的照片,我把很多照片剪成了两半。事实证明,驱动程序错误地假设所有照片数据在请求时都已被接收(通过TCP流),但通常只有部分数据可用。我必须安装一个网络嗅探器,对摄像头发送的数据结构进行反向工程,并使用此答案中提供的策略编写自己的驱动程序。嗨,是的,我确实看到了你的摄像头故事。我尝试了一些事情,但没有成功,但我会尝试这个。这整件事让我很扫兴,因为它在同一台机器上都很成功,但当它在不同的机器上运行时,就无法处理更大的数据消息。UDP的一切都很好,但我需要消息对消息的可靠性。谢谢我明天早上再查如果有数据报