偶尔读读C#TCP客户端接收不到数据 - “无”
问题描述:
我写这与服务器通信的TCP客户端。在专门的“聆听”线程中,我拥有如下代码。只有在那里有数据时才应该读取数据。 ()偶尔读读C#TCP客户端接收不到数据 - “无”
奇怪的是,偶尔我,程序将会崩溃,因为流将读取绝对没有数据。它将返回一个空的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);
}
}
}
}
引发的异常是System.NullReferenceException
在handleResponse
功能
答
网络流有可用的广告数据的习惯,即使他们不活跃的线if ((desrlzdResp.instruction != null))
。此外,接收者无法知道传入流是多长时间,除非发送者事先通告它。
/// <summary>
/// Method designed to allow the sending of Byte[] data to the Peer
/// Because this is using NetworkStreams - the first 4 bytes sent is the data length
/// </summary>
/// <param name="TheMessage"></param>
public void SendBytesToPeer(byte[] TheMessage)
{
try
{
long len = TheMessage.Length;
byte[] Bytelen = BitConverter.GetBytes(len);
PeerStream.Write(Bytelen, 0, Bytelen.Length);
PeerStream.Flush();
PeerStream.Write(TheMessage, 0, TheMessage.Length);
PeerStream.Flush();
}
catch (Exception e)
{
//System.Windows.Forms.MessageBox.Show(e.ToString());
}
}
注 - 在发送端的冲洗可能并不需要,但我将其添加在,因为它没有坏处 - 微软表示,冲洗无助于网络流。
所以这个代码将决定您要发送的邮件的大小,然后发送给你的未来“实际”消息的接收者。
/// <summary>
/// Incoming bytes are retieved in this method
/// </summary>
/// <param name="disconnected"></param>
/// <returns></returns>
private byte[] ReceivedBytes(ref bool disconnected)
{
try
{
//byte[] myReadBuffer = new byte[1024];
int receivedDataLength = 0;
byte[] data = { };
int len = 0;
int i = 0;
PeerStream.ReadTimeout = 15000;
if (PeerStream.CanRead)
{
//networkStream.Read(byteLen, 0, 8)
byte[] byteLen = new byte[8];
if (_client.Client.IsConnected() == false)
{
//Fire Disconnect event
if (OnDisconnect != null)
{
disconnected = true;
OnDisconnect(this);
return null;
}
}
while (len == 0)
{
PeerStream.Read(byteLen, 0, 8);
len = BitConverter.ToInt32(byteLen, 0);
}
data = new byte[len];
PeerStream.Read(data, receivedDataLength, len);
return data;
}
}
catch (Exception E)
{
//System.Windows.Forms.MessageBox.Show("Exception:" + E.ToString());
}
return null;
}
此代码将等待,直到接收方检测到传入流的长度,然后它会尝试读取确切的长度。 不要担心OnDisconnect比特,这只是一些代码,我从一个项目,我是做留英寸您可能需要考虑在while(len == 0)循环内添加Thread.Sleep,以节省您的CPU周期。
你假设一个发送()对应于一个接收(),但是这并不插槽如何工作。 'responseData'可以包含一个消息,多个或部分消息。您需要一个成帧协议来区分这些情况,例如,通过在数据前加上一个数字来指示后续有多少字节。尝试seaching。 – CodeCaster
好吧,看起来'desrlzdResp'为空,因此在'JSONDataObject desrlzdResp = JsonDataverthe.DeserializeObject(msg)之后添加'if(desrlzdResp!= null)'''应该避免null参考异常 –
Pikoh
@Pikoh不,那么你会失去数据。 'handleResponse()'可以接收部分或多个消息,导致'JsonConvert.DeserializeObject()'失败。 OP需要确保他们只用完整的消息调用'handleResponse()'。 – CodeCaster