我已經編寫了一個應用程序,用於偵聽端口並接收一些數據包,根據我的定製協議,數據包爲49字節到1500字節,我可以從數據長度數據包。我應該解釋和處理49字節數據包和更大數據包的方式是不同的。從TCP客戶端接收數據時出錯
問題是,當我收到小於1374字節的數據包時,一切正常,但是當數據包長度變得更大時,我收到以下異常,並且我還丟失了4個數據的最後一個字節(我用1384byte數據包,我丟失了最後4個字節)
引發的異常: 索引超出範圍。必須是非負數且小於集合的大小。 參數名稱:startIndex
每個49字節的數據包有35個字節的數據,並且較大數據包的數據長度是非確定性的(由於壓縮)。
我發現有時最後4個字節是在一個單獨的「字節」和「結果」變量中,這意味着它們被當作新數據包來處理,並且不會被附加到它們所屬的數據包上。
這裏是用於接收數據的代碼:
TcpClient Client = obj as TcpClient;
EndPoint ep = Client.Client.RemoteEndPoint;
List<Byte> result = new List<byte>();
result.Capacity = 2000;
try
{
NetworkStream stream = Client.GetStream();
int i = 49;
while ((i = stream.Read(bytes, 0,49)) != 0)
{
for (int id = 0; id < i; id++)
{
result.Add(bytes[id]);
}
//reading data length to determine packet length
byte[] tmp = new byte[2];
tmp = BitConverter.GetBytes(BitConverter.ToUInt16(result.ToArray(), 9));
if (BitConverter.IsLittleEndian)
{
Array.Reverse(tmp);
}
Int16 l = BitConverter.ToInt16(tmp, 0);
if (l>35)
{
stream.Read(bytes, result.Count, l - 35);
for (int id = 49; id <((l-35)+49); id++)
{
result.Add(bytes[id]);
}
if (this.TCPDataReceivedHandler != null)
{
this.TCPDataReceivedHandler(ep, result.Count, result.ToArray());
result.Clear();
Array.Clear(bytes, 0, 2000);
result.Capacity = 2000;
}
}
else
{
if (this.TCPDataReceivedHandler != null)
{
this.TCPDataReceivedHandler(ep, result.Count, result.ToArray());
result.Clear();
Array.Clear(bytes, 0, 2000);
result.Capacity = 2000;
}
}
}
System.Diagnostics.Debug.WriteLine("client Close");
Client.Close();
}
catch (System.Exception ex)
{
throw ex;
}
finally
{
Client.Close();
this.clients.Remove(Client);
}
據格雷格建議和我的研究,我還用以下方法嘗試:
NetworkStream stream = Client.GetStream();
int bytesread = 0, OffsetTemp = 0;
while (stream.CanRead)
{
OffsetTemp = 0;
bytesread += stream.Read(bytess, OffsetTemp, 11);
OffsetTemp = OffsetTemp + 11;
byte[] tmp = new byte[2];
tmp = BitConverter.GetBytes(BitConverter.ToUInt16(bytess.ToArray(), 9));
if (BitConverter.IsLittleEndian)
{
Array.Reverse(tmp);
}
Int16 l = BitConverter.ToInt16(tmp, 0);
bytesread += stream.Read(bytess, OffsetTemp++, 11 + l + 3);
for (int id = 0; id < l + 14; id++)
{
result.Add(bytess[id]);
}
if (this.TCPDataReceivedHandler != null)
{
this.TCPDataReceivedHandler(ep, result.Count, result.ToArray());
result.Clear();
Array.Clear(bytess, 0, 2000);
}
}
感謝格雷格,但我怎麼能確信,數據包不會互相混淆,如果我繼續從stream.Read()讀取而不注意數據包中的數據長度字段?數據包以短時間連續發送。 –
它看起來像你的協議有一個標題,指定下面的數據塊的長度。所以對於當前塊只讀很多,然後循環到頂部並讀取下一個塊的長度標題。 –
親愛的格雷格,我試着用你的建議,但沒有工作,我仍然有問題接收超過1380字節的數據。 –