关于Socket传输流的序列化与反序列化

本文展示了如何使用Socket进行网络通信时,实现自定义对象的序列化和反序列化。通过示例代码,客户端创建Socket连接,将`DataTest`对象序列化后发送给服务器。服务器端接收数据并反序列化回`DataTest`对象。关键点包括:1. 使用`[Serializable]`标记序列化类;2. 共享dll文件确保客户端和服务器端类定义一致;3. 注意处理序列化和反序列化可能出现的异常。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我想做的是 将一个自定义对象序列化后传输到网络的另一边,然后在接收端再反序列化


//客户端代码如下

public class ClientControlManager
    {
        #region 单例
        static ClientControlManager instance;
        public static ClientControlManager Instance
        {
            get
            {
                if (instance == null)
                    instance = new ClientControlManager();
                return instance;
            }
        }

        private ClientControlManager() {}
        #endregion

        Socket          _clientSocket;
 
        /// <summary>连接服务器</summary>
        public void ConnectionServer()
        {
            _clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            _clientSocket.NoDelay = true;

            IPAddress ipAddress = IPAddress.Parse(Config.ipAddress);
            IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, Config.portId);

            _clientSocket.BeginConnect(ipEndPoint, ConnetCallback, _clientSocket);//

        }


        private void ConnetCallback(object resultObj)
        {
            Console.WriteLine("连接服务器成功.....................");

            DataTest dt = new DataTest();
            dt.i1 = 3;
            dt.i2 = 4;
            dt.f = 5.6f;


            SendMsg(dt);
           
        }


        /// <summary>
        /// 发送消息
        /// </summary>
        public void SendMsg(object msg)
        {

            Console.WriteLine("发送消息到服务器................");
            using (MemoryStream memory = new MemoryStream())
            {
                BinaryFormatter formatter = new BinaryFormatter();
                formatter.Serialize(memory, msg);

                Console.WriteLine("发送长度:" + memory.ToArray().Length);
                _clientSocket.Send(memory.ToArray());
            }
        }


    }



class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("客户端开启");

            ClientControlManager.Instance.ConnectionServer();

            Console.ReadLine();

        }
    }





//服务器端代码如下:

public class NetworkControlManager
    {
        # region 单例
        static NetworkControlManager _instance;
        public static NetworkControlManager Instance
        {
            get
            {
                if (_instance == null)
                    _instance = new NetworkControlManager();
                return _instance;
            }
        }

private NetworkControlManager(){}


        #endregion


        Socket _serverSocket;        //服务套接字


        /// <summary>初始化服务</summary>
        public void InitService()
        {

            _serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            _serverSocket.NoDelay = true;

            IPAddress idAddress = IPAddress.Parse("127.0.0.1");//服务器主机地址
            _serverSocket.Bind(new IPEndPoint(idAddress, Config.portID));
            _serverSocket.Listen(50);

            Console.WriteLine("开启服务器...............");
            Thread listenThread = new Thread(ListenClient);
            listenThread.Start();
        }

        /// <summary>开启的一个线程,监听客户端</summary>
        private void ListenClient()
        {
            Console.WriteLine("监听客户端.......................");

            while (true)
            {
                Socket clientSocket= _serverSocket.Accept();//阻塞状态
                Thread clientThread = new Thread(HandleClient);

                clientThread.Start(clientSocket);
            }
        }

        /// <summary>每个客户端都在这里处理,这里是多线程</summary>
        private void HandleClient(object clientSocketObj)
        {
            byte[] result = new byte[1024];

            Socket ClientSocket = clientSocketObj as Socket;

            List<byte> listByte = new List<byte>();
            try
            {
                while (true)
                {
                    int byteCount = ClientSocket.Receive(result);

                    if (result.Length == byteCount)
                        listByte.AddRange(result);
                    else
                    {
                        for (int i = 0; i < byteCount; i++)
                            listByte.Add(result[i]);
                        break;
                    }
                   
                }
                using (MemoryStream m = new MemoryStream(listByte.ToArray()))
                {
                    BinaryFormatter bf = new BinaryFormatter();

                    Console.WriteLine("m.length" + m.ToArray().Length);

                    object dataObj = bf.Deserialize(m);
                    DataTest dt = dataObj as DataTest;

                    
                   Console.WriteLine("接收客户端长度:" + listByte.Count+"     i1:" + dt.i1 + " i2:" + dt.i2 + " f:" + dt.f);
                   

                }
               
            }
            catch (Exception e)
            {
                Console.WriteLine(e.StackTrace);
            }
           

        }



    }


class Program
    {
        static void Main(string[] args)
        {
            NetworkControlManager.Instance.InitService();
        }
    }





//自定义类型

[Serializable]
 public class DataTest
 {
     public int i1;
     public int i2;
     public float f;
 }



注意:

1.序列化对象的class必须要声明为[Serializable]

MemoryStream memory = new MemoryStream()
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(memory, msg);//否则这里会序列化失败,抛出异常


2.序列化对象的类如果分别是在客户端和服务器端自定定义,在接收端反序列化的时候会反序列化失败,我的解决方法是把这个class生成一个dll文件,然后两端都使用这个dll文件的class. 我确实弄不懂谷歌的protocol Buffer的自定义class是怎么做到这一点的


3.生成自定义类型dll

新建一个项目选择创建类库,完成编码后,在项目上右击->生成  然在项目文件夹里找到生成的dll文件,将这个文件引用到服务器端和客户端就可以了



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值