如何通过C#中的数据包读取传入的TCP数据包(即没有连接数据包)?

时间:2018-03-20 09:29:12

标签: c# tcpclient

我实际上是从Matlab发送数据来更新UNITY场景: - Matlab使用TCP协议向UNITY发送“a”或“b” - UNITY接收“a”或“b”,并更新颜色基于此字符的对象

我在UNITY中更新了名为“coherence”的变量时遇到了问题。当脚本运行时,来自MATLAB的数据包正在连接。例如,如果我在日志文件中打印“coherence”,它看起来像“aaaaababbbbbbbbaaaaabbbbbbababababbbbaaababbaabbbaba”。我想要的是,我的最后一个数据包是唯一要读取和打印的数据包(例如,“coherence”是“a”,然后是“b”,然后是“b”,然后是“a”等等,而不是“a”然后“ab”然后“abb”然后“abba”...)。

请问我的代码中有什么问题可以告诉我吗?指令“ReadToEnd”是否正常?

非常感谢您的投入,

的Yannick

// Use this for initialization of TCP Server 

TcpListener listener; 
String coherence;

// Initialization of the script 
void Start() 
{ 
     _renderer = GetComponent(); 
listener = new TcpListener(55001); 
listener.Start(); 
print("is listening"); 
}

void Update() 
{

                     if (!listener.Pending())
                     {
                     }
                     else
                     {
                         print("socket comes");
                         TcpClient client = listener.AcceptTcpClient();
                         NetworkStream ns = client.GetStream();
                         StreamReader reader = new StreamReader(ns);
                         coherence = reader.ReadToEnd();
                         print(coherence);
                     }



             if (coherence == "a")
             {
                 colorFin = Color.green;
             }

             else if (coherence == "b")
             {
                 colorFin = Color.yellow;
             }
}

1 个答案:

答案 0 :(得分:1)

与UDP不同,TCP在逻辑上是流API,而不是数据包API。虽然在某些低级别可能来访问原始数据包,但几乎所有消费者 API都将其作为流公开,并不保证接收将匹配发送方式原始数据包布局。相反,保证的是:相同的字节,相同的顺序。这意味着你需要实现某种类型的框架"协议。对于基于文本的协议,这通常意味着简单:行 - 即在每个完整消息之后添加CR / LF / CRLF。对于二进制协议,这通常意味着每个完整消息之前的某种长度前缀

请注意ReadToEnd()仅在您希望所有数据一次出现时(而不是通过两个端点之间的x / y / x / y / x / y对话)才可用;虽然我个人建议在使用套接字时完全避免使用StreamReader ,并且只使用原始套接字API或流API。像ReadToEnd这样的代码很容易永远阻止。如果这是一个只需要单个套接字的客户端,那可能没问题,但对于服务器(有很多套接字),这很糟糕:恶意客户端可以通过简单地发送"Hi"而不是断开连接来永久锁定线程 。这永远不会满足ReadToEnd