zoukankan      html  css  js  c++  java
  • Socket异步通信学习二

    接下来是服务器部分,采用异步模式,新建了一个AsynServer类,用于存放socket服务器代码,主要有4个方法:

    有一个全局socket,下面四个方法中都用到。

    Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

    类框架如下:

    1.构造方法public AsynServer(IPEndPoint endpoint,int listenMaxNum)

      用于初始化socket服务器,IPEndPoint参数是socket绑定的终结点,listenMaxNum参数是监听队列的挂起的最大长度,代码如下:

      public AsynServer(IPEndPoint endpoint,int listenMaxNum)
            {       
                    socket.Bind(endpoint);      //绑定终结点
                    socket.Listen(listenMaxNum);//将socket至于侦听状态,设置挂起队列最大值为listenMaxNum
                    Console.WriteLine("正在连接客户端....");
                    AsynAccept();         //开始异步监听
           //     return socket;
            }

    2.异步监听方法public void AsynAccept()

    public void AsynAccept()
            {
                    socket.BeginAccept(asyncResult => {
                    socket = socket.EndAccept(asyncResult);         //异步监听成功,返回socket
                    Console.WriteLine("客户端{0}异步连接成功", socket.RemoteEndPoint.ToString());            
                    AsynReceive();
                        AsynSend("Server:Hello,client!");
                }, null);
            }
    View Code

    需注意的是异步socket的BeginAccept()方法必须以EndAccept()方法结束,EndAccept(asyncResult)通过回调BeginAccept中的asyncResult状态信息返回socket,这个socket是与客户端建立连接后的socket,需要把它赋给全局socket(后面的方法中会调用)。

    另外,AsynAccept并不会阻塞主线程,因为系统会为BeginAccept()方法自动开一个线程,并阻塞该线程直到收到客户端连接,回调lamda表达式中的接收代码。

    采用lamda变得式写的回调函数,不熟悉的同学请恶补一下吧,用起来很方便的:-)

    连接成功了会收到客户端发来的信息,(AsynReceive()也是异步的,不会阻碍主线程),并给客户端发送问候信息,(AsynReceive()和AsynSend()都是异步的,不会阻碍主线程)。

    3.异步接收方法private  void AsynReceive()

      private  void AsynReceive()
            {
                byte[] data = new byte[1024];//接收缓存
                string receiveStr;
                socket.BeginReceive(data, 0, data.Length, SocketFlags.None, asyncResult => {
                    int length = socket.EndReceive(asyncResult);
                    if (length != 0)
                    {
                        receiveStr = Encoding.ASCII.GetString(data, 0, length);//获取缓存中的信息
                        Console.WriteLine(receiveStr);
                          
                        AsynReceive();//继续开新线程接收
                    }
                    else {
                            
                        Console.WriteLine("客户端{0}:关闭socket连接", socket.RemoteEndPoint.ToString());//socket.RemoteEndPoint.ToString()是客户端IP地址
                        socket.Close();
                    }
                }, null);
                
                
            }
    AsynReceive()

    4.异步发送方法public void AsynSend()

     public void AsynSend(string msg)
            {
                byte[] data = Encoding.UTF8.GetBytes(msg);
                socket.BeginSend(data, 0, data.Length, SocketFlags.None, asyncResult =>
                {
                    int length = socket.EndSend(asyncResult);
                    Console.WriteLine("message send to {0} successfully", socket.RemoteEndPoint.ToString());
                }, null);            
            }
    public void AsynSend(string msg)

    因为socket收发都是采用字节流的形式,所以接收需要用byte[] data = new byte[1024],缓存收到的字节流,然后通过Encoding.ASCII.GetString(data, 0, length)方法把字节流转化为字符串输出;发送通过byte[] data = Encoding.UTF8.GetBytes(msg),把字符串信息转化为字节流发送。EndReceive(),EndSend()方法返回的都是收发字节数(int)

    以上都是最简单的,只能实现基本的通信功能,后期会在此基础上完善,帮助初学者少走弯路,我当时可是学的头昏眼花-_-||

    下篇是采用与服务器完全不同模式的客户端,同步模式

  • 相关阅读:
    android kl文件
    ELF文件结构描述
    jquery开头
    win7无声音显示“未插入扬声器或耳机” 怎么解决
    xhtml头文件设置
    break和continue的区别
    php目录函数
    mysql语法
    php中怎么导入自己写的类
    截取文件后缀名
  • 原文地址:https://www.cnblogs.com/gongheng/p/5683241.html
Copyright © 2011-2022 走看看