Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/340.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
数据丢失TCP IP C#_C#_Networking_Serialization_Tcp_Packet - Fatal编程技术网

数据丢失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之上实现自己的打包逻辑

有两种常见的打包方法:

  • 分隔符字符,这通常用于文本协议中,新行是常见的选择
  • 为每个数据包添加前缀长度,这通常是二进制协议的一个好选择
  • 您将逻辑数据包的大小存储在该数据包的开头。然后进行读取,直到收到足够的字节来填充数据包并开始反序列化

    在我尝试构建数据并对其进行处理之前,如何确保已接收到所有数据

    你必须实现一些协议,这样你就知道了

    虽然TCP是可靠的,但它不能保证套接字一端的单次写入数据在另一端显示为单次读取:重试、数据包碎片和MTU都会导致接收器以不同大小的单位接收数据。您将以正确的顺序获取数据

    因此,在发送时,您需要包含一些信息,以便接收方知道何时收到完整的消息。我还建议包括什么类型的消息和数据的版本(这将构成能够同时支持不同客户端和服务器版本的基础)

    因此,发送方发送: -消息类型 -消息版本 -消息大小(以字节为单位)

    接收器将循环,使用缓冲区执行读取,并将其附加到主缓冲区(这很好)。一旦接收到完整的报头,它就知道何时接收到完整的数据


    (另一种方法是包含一些模式作为“消息结束”标记,但如果数据是二进制而不是文本,则需要处理内容中出现的相同字节序列,这是很难做到的。)

    简单想想。。。您是否在反序列化数据之前尝试调用stream.Flush()?只是为了确保数据在反序列化之前就在那里,我没有尝试过;我刚才试过了,没什么变化。长度的前缀是什么?这似乎是一条路要走。我在想:序列化数据,获取字节的长度,序列化长度,创建新的字节数组并将长度放在第一位,数据放在第二位。发送数据。唯一的问题是,在我知道我有足够的数据来重建前缀之前,我不知道要读取多远。你可以使前缀的大小保持不变,例如4个字节。我认为如果大小标头不是一块发送的,那么你的代码仍然存在错误。然后你混合同步和异步读取是一种奇怪的方式,但这不会导致直接错误,但是性能降低了,我不知道怎么做。如果您不介意发布一个例子,我将不胜感激。演出似乎不太好