zoukankan      html  css  js  c++  java
  • C# Socket系列一 简单的创建socket的监听

    socket的应用场景,在快速,稳定,保持长连接的数据传输代码。Http也是socket封装出来的,基于一次请求一次回复,然后断开的socket连接封装。

    比如我们常见的游戏服务器,目前的很火的物联网服务器,都需要开启socket服务器去监听实时传输的数据。

    那么我们如何实现socket的监听呢。说到这里,我们需要知道,socket的监听分为tcp和udp两种形式,但是tcp其实是udp封装而来的,可看做可靠的udp传输,基于udp的定向传输,收到消息回复发送方收到消息。等验证,来实现tcp的数据传输,所以一般我们tcp的传输相对udp稍微慢一点。

    我们先将一下socket 的tcp状态创建一个TCPListener类

      1  /// <summary>
      2     /// 建立TCP通信监听服务
      3     /// </summary>
      4     internal class TCPListener
      5     {
      6         private IPEndPoint _IP;
      7         private Socket _Listeners;
      8         private volatile bool IsInit = false;
      9         List<TSocketBase> sockets = new List<TSocketBase>();
     10 
     11         /// <summary>
     12         /// 初始化服务器
     13         /// </summary>
     14         public TCPListener(string ip = "0.0.0.0", int port = 9527)
     15         {
     16             IsInit = true;
     17             IPEndPoint localEP = new IPEndPoint(IPAddress.Parse(ip), port);
     18             this._IP = localEP;
     19             try
     20             {
     21                 Console.WriteLine(string.Format("Listen Tcp -> {0}:{1} ", ip, port));
     22                 this._Listeners = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
     23                 this._Listeners.Bind(this._IP);
     24                 this._Listeners.Listen(5000);
     25                 SocketAsyncEventArgs sea = new SocketAsyncEventArgs();
     26                 sea.Completed += new EventHandler<SocketAsyncEventArgs>(this.AcceptAsync_Async);
     27                 this.AcceptAsync(sea);
     28             }
     29             catch (Exception ex)
     30             {
     31                 Console.WriteLine(ex);
     32                 this.Dispose();
     33             }
     34         }
     35 
     36         private void AcceptAsync(SocketAsyncEventArgs sae)
     37         {
     38             if (IsInit)
     39             {
     40                 if (!this._Listeners.AcceptAsync(sae))
     41                 {
     42                     AcceptAsync_Async(this, sae);
     43                 }
     44             }
     45             else
     46             {
     47                 if (sae != null)
     48                 {
     49                     sae.Dispose();
     50                 }
     51             }
     52         }
     53 
     54         private void AcceptAsync_Async(object sender, SocketAsyncEventArgs sae)
     55         {
     56             if (sae.SocketError == SocketError.Success)
     57             {
     58                 var socket = new TSocketClient(sae.AcceptSocket);
     59                 sockets.Add(socket);
     60                 Console.WriteLine("Remote Socket LocalEndPoint:" + sae.AcceptSocket.LocalEndPoint + " RemoteEndPoint:" + sae.AcceptSocket.RemoteEndPoint.ToString());
     61             }
     62             sae.AcceptSocket = null;
     63             if (IsInit)
     64             {
     65                 this._Listeners.AcceptAsync(sae);
     66             }
     67             else { sae.Dispose(); }
     68         }
     69 
     70         /// <summary>
     71         /// 释放资源
     72         /// </summary>
     73         public void Dispose()
     74         {
     75             if (IsInit)
     76             {
     77                 IsInit = false;
     78                 this.Dispose(true);
     79                 GC.SuppressFinalize(this);
     80             }
     81         }
     82         /// <summary>
     83         /// 释放所占用的资源
     84         /// </summary>
     85         /// <param name="flag1"></param>
     86         protected virtual void Dispose([MarshalAs(UnmanagedType.U1)] bool flag1)
     87         {
     88             if (flag1)
     89             {
     90                 if (_Listeners != null)
     91                 {
     92                     try
     93                     {
     94                         Console.WriteLine(string.Format("Stop Listener Tcp -> {0}:{1} ", this.IP.Address.ToString(), this.IP.Port));
     95                         _Listeners.Close();
     96                         _Listeners.Dispose();
     97                     }
     98                     catch { }
     99                 }
    100             }
    101         }
    102 
    103         /// <summary>
    104         /// 获取绑定终结点
    105         /// </summary>
    106         public IPEndPoint IP { get { return this._IP; } }
    107     }

    主要两点我们socket的初始化代码 new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);初始化的类型是基于tcp。

    还有就是我们绑定ip地址,过去很多人socket的bind地址习惯写成127.0.0.1(测试环境)或者读取网卡信息,读取ip地址,这样麻烦,代码要写很多,切不符合多网卡多线路实际环境。我们用0.0.0.0是表示开启ipv4的所有线路监听,包括你的多路网卡,以及127.0.0.1

    1     class Program
    2     {
    3         static void Main(string[] args)
    4         {
    5             TCPListener tcp = new TCPListener();
    6             Console.ReadLine();
    7         }
    8     }

    我们运行看一下效果

    接下来我们使用telnet测试一下

    开启telnet

    然后打开cmd 

    输入 telnet 127.0.0.1 9527

    我们看到收到了一个连接

    跪求保留标示符
    /**
     * @author: Troy.Chen(失足程序员, 15388152619)
     * @version: 2021-07-20 10:55
     **/
    
    C#版本代码 vs2010及以上工具可以
    
    java 开发工具是netbeans 和 idea 版本,只有项目导入如果出现异常,请根据自己的工具调整
    
    
    提供免费仓储。
    最新的代码地址:↓↓↓
    https://gitee.com/wuxindao
    
    觉得我还可以,打赏一下吧,你的肯定是我努力的最大动力
        
    
  • 相关阅读:
    mysql的binlog日志格式
    Git的基本使用
    Tomcat安装部署
    [ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (111)]
    云盘的创建及使用
    ntp服务器配置
    如何更改mysql的密码策略?
    Centos6 升级glibc-2.17,解决Requires: libc.so.6(GLIBC_2.14)(64bit)错误解决方法
    Git的基本使用
    UES
  • 原文地址:https://www.cnblogs.com/shizuchengxuyuan/p/4344495.html
Copyright © 2011-2022 走看看