【发布时间】:2016-01-26 11:00:44
【问题描述】:
我编写了一个与服务器通信的 TCP 客户端。在一个专门的“监听”线程中,我有如下代码。它应该只在有一些数据时读取数据。 (if (stream.DataAvailable))
奇怪的是,有时我的程序会崩溃,因为流绝对不会读取任何数据。它将返回一个空的string。更奇怪的是,如果我尝试在 handleResponse(string s) 函数中“捕获”一个空字符串,它不会被捕获。
public void listenForResponses()
{
Console.WriteLine ("Listening...");
while (isConnected == true)
{
Thread.Sleep (updateRate);
String responseData = String.Empty;
if (stream.DataAvailable) {
Int32 bytes = stream.Read (data, 0, data.Length);
Console.WriteLine (" >> Data size = "+data.Length);
responseData = System.Text.Encoding.ASCII.GetString (data, 0, bytes);
output = responseData+"";
handleResponse (output);
}
if (isConnected == false) {
closeConnection ();
}
}
}
public void handleResponse(string msg)
{
Console.WriteLine ("Received: "+msg);
iterateThroughEachCharInString (msg);
if ((msg != "")&&(msg != null)&&(msg != " ")) {
JSONDataObject desrlzdResp = JsonConvert.DeserializeObject<JSONDataObject>(msg);
if ((desrlzdResp.instruction != null)) {
if (desrlzdResp.instruction == "TestConn") {
handleTestConn (desrlzdResp);
} else if (desrlzdResp.instruction == "SceneOver") {
handleSceneFinished (desrlzdResp);
}
}
}
}
抛出的异常是handleResponse函数的if ((desrlzdResp.instruction != null))行上的System.NullReferenceException
【问题讨论】:
-
您假设一个 Send() 对应一个 Receive(),但这不是套接字的工作方式。
responseData可以包含一条消息、多条消息或部分消息。您需要一个成帧协议来区分这些情况,例如通过在您的数据前面加上一个数字,指示后面有多少字节。尝试搜索。 -
嗯,看来
desrlzdResp为空,所以在JSONDataObject desrlzdResp = JsonConvert.DeserializeObject<JSONDataObject>(msg);之后添加if (desrlzdResp != null)..应该可以避免空引用异常 -
@Pikoh 不,那么您将丢失数据。
handleResponse()可以接收部分或多条消息,导致JsonConvert.DeserializeObject()失败。 OP 需要确保他们只使用完整的消息调用handleResponse()。 -
@CodeCaster 当然你是绝对正确的,你的第一条评论就是要走的路。我的评论只是为了避免NullReference Exception,显然不是解决背后的逻辑:)
-
您的 json 反序列化工作不正常。在没有看到您的数据的情况下,进一步评论很棘手。我认为成帧协议是由包含长度的消息的前几个字节处理的——尽管可能表明了一种不太基本的成帧机制。您还需要处理少于完整消息的帧。
标签: c# string tcp tcpclient tcp-ip