C# Socket系列一 简单的创建socket的监听

8/3/2015来源:C#应用人气:2189

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

我们看到收到了一个连接