Socket学习心得

首先不得不说之前对Socket的理解有很大的误区,在这里特别更正一下.

SOCKET是Java(C#)实现数据通信的API。
这个词语起源于BSD相关的UNIX,程序开发中用于process之间通信的API名称。

TCP/UDP是OSI模型的第四层中定义的两种通信方式。

也就是说,SOCKET是API,而TCP/UPD是通信协议,两种根本不同的东西。

语言表达的例子:
用Socket实现TCP(或者UDP)通信。 (相反,TCP或者UDP通信也可以不使用SOCKET实现)

也就是说Socket是TCP、UDP的实现方式,用SOCKET编程可以实现TCP、UDP的通信

附上Socket调用方法

流程:
服务器
设置要监听的IP和端口
创建服务器Socket实例(insSocket),指定需要的枚举参数
调用insSocket的Bind方法,传入要监听的IPAddress实例
调用insSocket的Listen方法,参数为挂起连接队列的最大长度,将insSocket设置为监听状态
因为监听是在不断循环监听的,所以开启一个单独的线程(可以保证界面流畅)

调用insSocket的Accept方法,返回一个新的Socket连接(newSocket)(newSocket的RemoteEndPoint为远程地址,LocalEndPoint为本地地址)
//建立一个私有字典,键是远程字符串地址,值是其实例的引用,发送消息可根据地址来确定实例
开始循环newSocket来不断的接收newSocket发来的消息,因为是循环,所以开启一个单独的线程
调用newSocket的Receive方法来接收发送来的信息,返回值为信息的长度,传入参数为byte[]数组,在返回长度的时候会讲远程发来的byte[]字节流填充到其中
调动Encoding.UTF8.GetString方法会的字符串格式的消息,传入参数分别为byte[]字节数组,第一个要解码的字节的索引,要解码的字节数(也就是上一步的返回值)


群聊就是遍历一次所有连接的客户端发送一次信息而已

Demo(节省篇幅没有开启线程)
  IPEndPoint point = new IPEndPoint(IPAddress.Parse("192.168.0.10"),7171);
  Socket insSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
  //要在这些可能发生异常的地方加try/catch,这里节省篇幅就不加了
  insSocket.Bind(point);
  insSocket.Listen(500);
  //开启一个线程来处理insSocket不断处理新连接请求,
  //假设中括号是开启了一个后台的线程,这个委托需要传入一个参数,将insSocket传进去
    [
      while(true)
      {
      //每次有客户端请求时这里会创建它的实例newSocket
      Socket newSocket = insSocket.Accept();
      //开启一个线程循环处理实例发来的消息
      //假设中括号是开启了一个后台的线程,这个委托需要传入一个参数,将newSocket传进去
        [
          while(true)
          {
          //后期这里可以进行优化,现在这样写如果信息太大会导致接收不全或者假死状态
          byte[] buffer = new byte[1024 * 1024];
          int msgCount = newSocket.Receive(buffer);
          string Message = Encoding.UTF8.GetString(buffer,0,msgCount);
          }
        ]
      }

]

----------------------------------------------------------------------------------------------------------------    
客户端
设置要监听的IP和端口
创建客户端的Socket实例(insSocket),指定需要的枚举参数
调用insSocket的Connect方法,传入要监听的IPAddress实例,建立于主机的连接(主机的Accept会触发生成客户端的实例)
//循环接收服务器发来的信息,所以开启一个后台线程
[
  while(true)
  {
    //后期这里可以进行优化,现在这样写如果信息太大会导致接收不全或者假死状态
    byte[] buffer = new byte[1024 * 1024];
    int msgCount = newSocket.Receive(buffer);
    string Message = Encoding.UTF8.GetString(buffer,0,msgCount);
  }
]

客户端发送消息给服务器调用insSocket的Send方法,传入字节数组格式的信息

客户端和服务器发送期间可以将自己定义并且标记为可序列化的类调用BinaryFormatter下的Serialize方法传入一个流和要序列化的对象达到传输自定义类的目的

Demo

 /// <summary>
        /// 序列化
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="Unity"></param>
        /// <returns></returns>
        public static byte[] Serialize(T Unity)
        {
            byte[] buffer = new byte[1024 * 1024];
            using (MemoryStream mStream = new MemoryStream())
            {
                BinaryFormatter bformatter = new BinaryFormatter();
                bformatter.Serialize(mStream, Unity);
                mStream.Flush();
                mStream.Position = 0;
                mStream.Read(buffer, 0, buffer.Length);
            }
            return buffer;
        }
        /// <summary>
        /// 反序列化
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="buffer"></param>
        /// <returns></returns>
        public static T Deserialize(byte[] buffer)
        {
            using (MemoryStream mStream = new MemoryStream(buffer))
            {
                //mStream.Seek(0, SeekOrigin.Begin);
                mStream.Position = 0;
                BinaryFormatter bformatter = new BinaryFormatter();
                T model = (T)bformatter.Deserialize(mStream);
                return model;
            }
        }

现在遇到的问题是将RichTextBox中的Document调用System.Windows.Markup.XamlWriter.Save方法转换为字符串之后再反序列化的时候总提示错误"在分析完成之前就遇到流结尾",暂时还没搞明白是什么意思,这个疑惑先放在这里,希望有高手能给予解答,感激不尽

原文地址:https://www.cnblogs.com/houzhitong/p/2952753.html