Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.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
C# 套接字问题和OutOfMemory错误_C#_Sockets_Networking - Fatal编程技术网

C# 套接字问题和OutOfMemory错误

C# 套接字问题和OutOfMemory错误,c#,sockets,networking,C#,Sockets,Networking,我有个大问题。尝试创建一个应用程序,它必须有两个部分:服务器端和客户端。这两个部分必须以某种方式进行通信并交换对象。我决定使用套接字,因为我不熟悉WCF,我可以在同一台计算机上测试这两个部分(只需将它们放在127.0.0.1地址上进行侦听) 现在,当我试图从客户端发送一些“自定义”可序列化对象时,我在服务器端遇到了“OutOfMemory”异常!我读了一些关于套接字,发送/接收对象的方法,我尝试了一些在网上找到的代码,但没有成功!我不知道我的代码出了什么问题。 这是我的密码: 这是双方代码中定义

我有个大问题。尝试创建一个应用程序,它必须有两个部分:服务器端和客户端。这两个部分必须以某种方式进行通信并交换对象。我决定使用套接字,因为我不熟悉WCF,我可以在同一台计算机上测试这两个部分(只需将它们放在127.0.0.1地址上进行侦听)

现在,当我试图从客户端发送一些“自定义”可序列化对象时,我在服务器端遇到了“OutOfMemory”异常!我读了一些关于套接字,发送/接收对象的方法,我尝试了一些在网上找到的代码,但没有成功!我不知道我的代码出了什么问题。 这是我的密码:

这是双方代码中定义的测试类:

[Serializable]
    class MyClass
    {
        public string msg="default";
    }
客户端发送代码(工作正常):

服务器端代码(导致问题的代码):

所以,我在尝试反序列化时遇到了异常。我不知道怎么了


我威胁我的代码“如果你继续造成问题,我会向StackOverflow的家伙报告你”,所以我在这里:)

那里有一些非常奇怪的代码:

  • 假设我们未经检查就读取1024字节
  • 复制1024个缓冲区
  • 假定序列化数据为1024字节,不多不少
  • 从中反序列化

我认为这是你的错误;您应该从流中读取正确的字节数(通常在循环中)。通常,您会循环,检查读取的返回值,直到我们读取了所需的数据量,或者我们首先得到EOF(返回),虽然我不确定这是否是问题的直接原因,但您的读取逻辑存在严重问题

  • 您创建了一个1024字节的缓冲区,并在不检查实际读取了多少的情况下读取它;如果传入缓冲区只有56字节,您将只读取56字节(除非您在套接字本身上使用阻塞读取,这可能会超时)。同样,您的缓冲区中可能有2000个字节,这意味着您的缓冲区中还有976个字节,在收到更多数据之前无法处理。这可能是一个完整的对象,客户端可能会在发送更多数据之前等待对它的响应
  • 然后,获取该缓冲区并将其再次复制到
    MemoryStream
    中。与其这样做,不如获取获取缓冲区的
    MemoryStream
    构造函数的重载。这样就不会复制数据
  • 在处理传入数据后调用
    EndReceive
    ;虽然这实际上可能不会导致错误,但这并不符合
    Begin
    /
    End
    旧式异步模式的精神。您应该在回调开始时调用
    EndXXX
  • 我知道这不是对你问题的直接回答,但你确实需要重新考虑你不使用WCF的决定

    几个月前,我和你在同一条船上;我以前没有使用过WCF,我也懒得去看它是如何工作的。对我来说,它是一个非常大的黑匣子,我在其他平台上进行了基于套接字的通信,所以这是一个已知的数量。回过头来看,我选择涉足WCF是我能做的最好的决定一旦你对一些概念(绑定、契约以及如何使用各种属性)了如指掌,服务的开发就很简单了,你不必花时间编写管道

    NetTcpBinding
    提供了一个基于TCP的绑定,它可以支持长寿命的连接和会话(我就是这么使用它的),甚至可以通过可靠的会话处理保持活动消息以保持连接的打开状态。只需打开一个标志即可。如果您需要更具互操作性的东西(意味着跨平台),您可以编写自己的绑定来执行此操作,并保持代码不变


    请看一些TCP WCF示例;您不需要花费很长时间就可以启动并运行某些功能,一旦达到了这一点,修改就很简单,只需在接口中添加一个函数,然后在服务类中添加一个相应的函数。

    您是否查看了数据?内存中有什么?buffer.length的值是多少?等等@Richard是最后一个-一个残酷强制的1024;但这并不反映实际的数据长度:)@Marc Doh!是的。我没有仔细阅读代码,但试图指出一些基本的调试技术和信息,这些技术和信息可能会指向他的问题根源。@Richard绝对:)教一个人钓鱼等等,我从来没有编程过sockets,很少使用流,所以整个事情对我来说很混乱:\@guest86:如果你还没有编程套接字,那么这更像是使用WCF的信号。
    private void cmdSendData_Click(object sender, System.EventArgs e)
        {
            try
            {
                MyClass test = new MyClass();
    
                NetworkStream ns = new NetworkStream(m_socWorker); //m_socWorker is socket
                BinaryWriter bw = new BinaryWriter(ns);
    
                MemoryStream ms = new MemoryStream();
                BinaryFormatter bf = new BinaryFormatter();
                bf.Serialize(ms, test);
    
                bw.Write(ms.ToArray());
                MessageBox.Show("Length is: " + ms.ToArray().Length); //length is 152!
                ns.Close();
            }
            catch(System.Net.Sockets.SocketException se)
            {
                MessageBox.Show (se.Message );
            }
        }
    
    public  void OnDataReceived(IAsyncResult asyn)
        {
            try
            {
                CSocketPacket theSockId = (CSocketPacket)asyn.AsyncState ;
    
                NetworkStream ns = new NetworkStream(m_socWorker);
                byte[] buffer = new byte[1024];
                ns.Read(buffer, 0, buffer.Length);
    
                BinaryFormatter bin = new BinaryFormatter();
                MemoryStream mem = new MemoryStream(buffer.Length);
    
                mem.Write(buffer, 0, buffer.Length);
                mem.Seek(0, SeekOrigin.Begin);
                MyClass tst = (MyClass)bin.Deserialize(mem); //ERROR IS THROWN HERE!
    
                MessageBox.Show(tst.msg);
    
                theSockId.thisSocket.EndReceive(asyn);
    
                WaitForData(m_socWorker);
            }
            catch (ObjectDisposedException )
            {
                System.Diagnostics.Debugger.Log(0,"1","\nOnDataReceived: Socket has been closed\n");
            }
            catch(SocketException se)
            {
                MessageBox.Show (se.Message );
            }
        }