你的位置:首页 > ASP.net教程

[ASP.net教程]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 Program2   {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

 

我们看到收到了一个连接