使用TcpClient在LAN上传输数据不完全
本文关键字:传输 数据 不完全 LAN TcpClient 使用 | 更新日期: 2023-09-27 17:52:45
我通过局域网发送序列化数据,但有时信息丢失!流程如下:
发送者:-
string mydata
正在序列化 -
string mydata
转化为byte[] bytes_of_mydata
-
int size_of_mydata
为byte[] bytes_of_mydata
的长度 -
int size_of_mydata
本身变成byte[] bytes_size_of_mydata
-
byte[] bytes_of_mydata
和byte[] bytes_size_of_mydata
发送
接收机:
- 我第一次收到
byte[] bytes_size_of_mydata
- 从
byte[] bytes_size_of_mydata
中检索第二消息的长度int size_of_mydata
- 我收到
byte[] bytes_of_mydata
,知道确切的长度! - 然后将
byte[] bytes_of_mydata
转换为string mydata
- 反序列化
string mydata
这种方法通常在大多数情况下都有效,但有时我的数据没有完全传输,所以字符串不能反序列化。
我已经在"接收器"上调试了接收到的byte[]
。结果如下:
我得到第二条消息的大小:
int size_of_second_message = BitConverter.ToInt32(dataByteSize, 0); // 55185
我开始接收到字节数组的第二条消息:
Byte[] dataByte = new Byte[55185];
但是从位置5840开始,我开始接收0 (null),所以部分&;5840 - 55185&;都是"0":
byte[5836] = 53;
byte[5837] = 57;
byte[5838] = 54;
byte[5839] = 49;
byte[5840] = 0; // information ends to flow
byte[5841] = 0;
byte[5842] = 0;
byte[5843] = 0;
//....
byte[55185] = 0;
上面的例子来自一个实际的调试器!
那么问题是什么?就像在传输过程中失去了连接!!为什么会发生这种情况,我该如何应对这个问题?它不会"每次"都发生。基础。
这里是代码
发送:
//text_message - my original message
//Nw - network stream
MemoryStream Fs = new MemoryStream(ASCIIEncoding.Default.GetBytes(text_message));
Byte[] buffer = Fs.ToArray(); // total 55185 bytes (as in example)
Byte[] bufferSize = BitConverter.GetBytes(Fs.Length); // 32 bytes represent size
bufferSize = GetNewByteSize(bufferSize);
Nw.Write(bufferSize, 0, bufferSize.Length); // send size
Nw.Flush();
Nw.Write(buffer, 0, buffer.Length); // send message
Nw.Flush();
接收:
//get first(SIZE) bytes:
int ReadSize = 0; int maxSize = 32; // 32 - constant!
Byte[] dataByteSize = new Byte[maxSize];
int origsize;
using (var strm = new MemoryStream())
{
ReadSize = Nw.Read(dataByteSize, 0, maxSize);
strm.Write(dataByteSize, 0, ReadSize);
strm.Seek(0, SeekOrigin.Begin);
origsize = BitConverter.ToInt32(dataByteSize, 0); // origsize = 55185
}
Nw.Flush();
//get next(MESSAGE) bytes:
string message = ""; int thisRead = 0;
int max = Convert.ToInt32(origsize); // origsize = 55185
Byte[] dataByte = new Byte[max];
using (var strm = new MemoryStream())
{
thisRead = Nw.Read(dataByte, 0, max);
strm.Write(dataByte, 0, thisRead);
strm.Seek(0, SeekOrigin.Begin);
using (StreamReader reader = new StreamReader(strm))
{
message = reader.ReadToEnd();
}
}
Nw.Flush();
// message - the message that is being transmitted partly (sometimes)!
我本来不想把代码贴出来,但是你们经常要求"给我们看看你们做了什么",所以就在这里了!
编辑
临时修复是切换到StreamWriter, reader。
接收+发送(服务器):
NetworkStream Nw = new NetworkStream(handlerSocket.Client);
string toreceive = "";
StreamReader reader = new StreamReader(Nw);
toreceive = reader.ReadLine();
string text_message = "to send back";
StreamWriter writer = new StreamWriter(Nw);
writer.WriteLine(text_message);
writer.Flush();
Nw.Close();
Send + receive (client):
NetworkStream Nw = new NetworkStream(handlerSocket.Client);
StreamWriter writer = new StreamWriter(Nw);
writer.WriteLine("to send");
writer.Flush();
string toreceive = new StreamReader(Nw).ReadLine();
writer.Close();
Nw.Close();
我正在寻找关于原始问题的解决方案,但到目前为止,由于临时修复,一切都在工作
TCP是一个基于流的协议,允许您读取尚未接收到的尽可能多的数据。仅仅因为您在一个步骤中发送数据,就不能保证数据将在同一个块中被接收。你必须在接收端循环,直到你收到所有你预期的数据。
顺便说一下,我认为你的协议在开始时带有显式的长度字段真的很好,它弥补了简单的客户端代码(至少简单)。
前段时间我问了一个关于内置功能等待X字节数据可用的问题:. net阻塞套接字读取直到X字节可用?很遗憾,答案是否定的。