数据丢失TCP IP C#
这是我的密码:数据丢失TCP IP C#,c#,networking,serialization,tcp,packet,C#,Networking,Serialization,Tcp,Packet,这是我的密码: private void OnReceive(IAsyncResult result) { NetStateObject state = (NetStateObject)result.AsyncState; Socket client = state.Socket; int size = client.EndReceive(result); byte[] data = state.Buffer; object data = null; using (MemoryStre
private void OnReceive(IAsyncResult result)
{
NetStateObject state = (NetStateObject)result.AsyncState;
Socket client = state.Socket;
int size = client.EndReceive(result);
byte[] data = state.Buffer;
object data = null;
using (MemoryStream stream = new MemoryStream(data))
{
BinaryFormatter formatter = new BinaryFormatter();
data = formatter.Deserialize(stream);
}
//todo: something with data
client.BeginReceive(
state.Buffer,
0,
NetStateObject.BUFFER_SIZE,
SocketFlags.None,
OnReceive,
state
);
}
state.Buffer的最大大小为NetStateObject.Buffer\u size(1024)。首先,这是太大还是太小?第二,如果我发送了比这更大的数据,我的反序列化就会出错,因为它试图反序列化的对象没有所有的信息(因为没有发送所有的数据)。在我尝试构建数据并对其进行处理之前,如何确保已接收到所有数据
完成的工作代码
private void OnReceive(IAsyncResult result)
{
NetStateObject state = (NetStateObject)result.AsyncState;
Socket client = state.Socket;
try
{
//get the read data and see how many bytes we received
int bytesRead = client.EndReceive(result);
//store the data from the buffer
byte[] dataReceived = state.Buffer;
//this will hold the byte data for the number of bytes being received
byte[] totalBytesData = new byte[4];
//load the number byte data from the data received
for (int i = 0; i < 4; i++)
{
totalBytesData[i] = dataReceived[i];
}
//convert the number byte data to a numan readable integer
int totalBytes = BitConverter.ToInt32(totalBytesData, 0);
//create a new array with the length of the total bytes being received
byte[] data = new byte[totalBytes];
//load what is in the buffer into the data[]
for (int i = 0; i < bytesRead - 4; i++)
{
data[i] = state.Buffer[i + 4];
}
//receive packets from the connection until the number of bytes read is no longer less than we need
while (bytesRead < totalBytes + 4)
{
bytesRead += state.Socket.Receive(data, bytesRead - 4, totalBytes + 4 - bytesRead, SocketFlags.None);
}
CommandData commandData;
using (MemoryStream stream = new MemoryStream(data))
{
BinaryFormatter formatter = new BinaryFormatter();
commandData = (CommandData)formatter.Deserialize(stream);
}
ReceivedCommands.Enqueue(commandData);
client.BeginReceive(
state.Buffer,
0,
NetStateObject.BUFFER_SIZE,
SocketFlags.None,
OnReceive,
state
);
dataReceived = null;
totalBytesData = null;
data = null;
}
catch(Exception e)
{
Console.WriteLine("***********************");
Console.WriteLine(e.Source);
Console.WriteLine("***********************");
Console.WriteLine(e.Message);
Console.WriteLine("***********************");
Console.WriteLine(e.InnerException);
Console.WriteLine("***********************");
Console.WriteLine(e.StackTrace);
}
}
private void OnReceive(IAsyncResult结果)
{
NetStateObject状态=(NetStateObject)result.AsyncState;
socketclient=state.Socket;
尝试
{
//获取读取的数据并查看我们接收到的字节数
int bytesRead=client.EndReceive(结果);
//存储缓冲区中的数据
字节[]dataReceived=state.Buffer;
//这将保存接收字节数的字节数据
字节[]totalBytesData=新字节[4];
//从接收到的数据中加载数字字节数据
对于(int i=0;i<4;i++)
{
totalBytesData[i]=接收到的数据[i];
}
//将数字字节数据转换为numan可读的整数
int totalBytes=bit converter.ToInt32(totalBytesData,0);
//使用接收的总字节长度创建一个新数组
字节[]数据=新字节[totalBytes];
//将缓冲区中的内容加载到数据[]
for(int i=0;i
TCP是一种流协议。它没有包的概念。一个写调用可以在多个数据包中发送,多个写调用可以放在同一个数据包中。因此,您需要在TCP之上实现自己的打包逻辑
有两种常见的打包方法:
(另一种方法是包含一些模式作为“消息结束”标记,但如果数据是二进制而不是文本,则需要处理内容中出现的相同字节序列,这是很难做到的。)简单想想。。。您是否在反序列化数据之前尝试调用stream.Flush()?只是为了确保数据在反序列化之前就在那里,我没有尝试过;我刚才试过了,没什么变化。长度的前缀是什么?这似乎是一条路要走。我在想:序列化数据,获取字节的长度,序列化长度,创建新的字节数组并将长度放在第一位,数据放在第二位。发送数据。唯一的问题是,在我知道我有足够的数据来重建前缀之前,我不知道要读取多远。你可以使前缀的大小保持不变,例如4个字节。我认为如果大小标头不是一块发送的,那么你的代码仍然存在错误。然后你混合同步和异步读取是一种奇怪的方式,但这不会导致直接错误,但是性能降低了,我不知道怎么做。如果您不介意发布一个例子,我将不胜感激。演出似乎不太好