实现功能,能够随时发送数据,并且能够随时接收服务端发送过来的数据,能够判断服务端或端口网络的连接状态,随时查看与服务器通讯是否通畅。

        可以使用VS创建一个用户控件或创建一个类,来控制Socket通讯,代码成熟,建议做成用户控件,这样可以随时拖拽控件,写事件什么的都方便。

        在写Socket客户端之前,要知道Socket客户端接收数据,使用 的线程循环的方式,有数据接收到的时候,触发消息事件,在断开事件处理时,能够触发断开连接事件,这时要定义几个委托,承载事件的触发。

        public delegate void ReceiveBuffer(byte[] buffer);//收到消息时,传递消息Buffer的事件。

        public delegate void HostDisconnectionEvent();//断开连接时,触发的事件。

        我在使用的时候,习惯将委托单独放在一个.cs文件当,定义为委托事件类:DelegateEvent.cs

        还要考虑到,在Socket接收消息时,需要使用线程,那么在触发收到消息的事件后,如果需要修改界面上的参数或值,需要做控件的异步调用处理,这样处理起来太麻烦,而且处理不好,到时会有一堆的Bug,这是我在使用过程当中遇到的。那么有一没有办法不使用线程,让客户端循环接收消息呢?这时我想到了使用异步,最后又增加了一个异步收消息的委托:

        public delegate void AsyncReceivedClient(object sender);//异步收到消息时的委托,如果整个类当中只有一个客户端连接,可以不带参数。

        这时,委托类基本建完了,那么,这时需要定义代码了:

    创建一个TCPClient类,当然,这个类和System.Net.Sockets下的类不同,为了区分,我定义的命名空间为:System.Net.Securate.TCP,下面是定义的事件和参数:

 

/// <summary>
         /// 收到消息事件
         /// </summary>
         public ReceiveBuffer ReceiveComtemplate;
         /// <summary>
         /// 主机断开连接事件
         /// </summary>
         public HostDisconnectionEvent HostDisconnectedComtelplate;
         private string _Address;
         /// <summary>
         /// 获取或设置连接地址
         /// </summary>
         public string Address
         {
             get { return _Address; }
             set { _Address = value; }
         }
         private int _Port;
         /// <summary>
         /// 获取或设置端口号
         /// </summary>
         public int Port
         {
             get { return _Port; }
             set { _Port = value; }
         }
         private Socket tcpClient;
         /// <summary>
         /// 获取连接状态
         /// </summary>
         public bool IsConnected
         {
             get {
                 if (tcpClient == null)
                     return false;
                 return tcpClient.Connected;
             }
         }

        创建连接的启动事件,我写两种启动方式,一种是不带参的,一种是带参的,如下:

     

/// <summary>
         /// 打开连接
         /// </summary>
         /// <returns></returns>
         public bool Start()
         {
             return Start(_Address, _Port);
         }
         /// <summary>
         /// 打开连接
         /// </summary>
         /// <param name="ip">连接地址</param>
         /// <param name="port">连接端口号</param>
         /// <returns></returns>
         public bool Start(string ip, int port)
         {
             try
             {
                 _Address = ip;
                 _Port = port;
                 tcpClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                 IPAddress ipaddress = IPAddress.Parse(_Address);
                 tcpClient.Connect(ipaddress, port);
                 if (tcpClient.Connected)
                 {
                     AsyncReceivedClient rc = new AsyncReceivedClient(Receive);
                     rc.BeginInvoke(tcpClient, null, null);
                 }
                 return tcpClient.Connected;
             }
             catch (Exception ex)
             {
                 return false;
             }
         }

        需要注意的是:

 

AsyncReceivedClient rc = new AsyncReceivedClient(Receive);
         rc.BeginInvoke(tcpClient, null, null);

        这两行,实现的是异步委托带参的调用,实现随时接收服务端发送过来的消息。

      在客户端收消息时,需要判断服务端连接是否断开,在网上的介绍上,说使用socket.Poll(1, SelectMode.SelectRead)和socket.Available= 0来判断网络是否断开,但在实际上的使用当中,我使用第三方的服务端,使用这种方式,根本不能判断断开,后来我想,能不能开一个SocketCient,来判断服务端口是否正常,相当于telnet命令,在实际使用当中,还没遇到问题:

   

/// <summary>
         /// 接收消息
         /// </summary>
         /// <returns></returns>
         public void Receive(object o)
         {
             Socket s = o as Socket;
             bool IsConnected = true;
             while (s.Connected)
             {
                 try
                 {
                     int res = s.Available;
                     if (res > 0)
                     {
                         byte[] xxxx = new byte[res];
                         int nRead = s.Receive(xxxx);
                         byte[] buffer = new byte[nRead];
                         Array.Copy(xxxx, 0, buffer, 0, nRead);
                         if (ReceiveComtemplate != null)
                             ReceiveComtemplate(buffer);
                     }
                     else
                     {
                         try
                         {
                             Socket testSocket =
                                 new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                             testSocket.Connect(s.RemoteEndPoint);
                             if (!testSocket.Connected)
                             {
                                 Stop();
                                 IsConnected = false;
                                 goto EndReceive;
                             }
                             else
                             {
                                 testSocket.Shutdown(SocketShutdown.Both);
                                 testSocket.Close();
                             }
                         }
                         catch (Exception ex)
                         {
                             Stop();
                             IsConnected = false;
                             goto EndReceive;
                         }
                     }
                 }
                 catch (Exception ex)
                 {
                     Stop();
                     IsConnected = false;
                     goto EndReceive;
                 }
                 Thread.Sleep(100);
             }
             EndReceive:
             if (!IsConnected)
             {
                 if (HostDisconnectedComtelplate != null)
                     HostDisconnectedComtelplate();
             }
         }

        最后就是一个发送,一个停止,这个部分,基本和msdn上介绍的一样,没有什么特殊的处理:

     

/// <summary>
         /// 发送消息
         /// </summary>
         /// <param name="buffer">发送的数据</param>
         public void Send(byte[] buffer)
         {
             try
             {
                 if (tcpClient.Connected)
                 {
                     tcpClient.Send(buffer);
                 }
             }
             catch { }
         }
         /// <summary>
         /// 停止
         /// </summary>
         public void Stop()
         {
             try
             {
                 //tcpClient.Client.Shutdown(SocketShutdown.Both);
                 //tcpClient.Close();
                 tcpClient.Shutdown(SocketShutdown.Both);
                 tcpClient.Close();
             }
             catch (Exception ex)
             { }
         }

        到这里基本上已经完成,完整代码如下,如果有不同看法或有更好的意见,欢迎在线留言:

using System;
 using System.Collections.Generic;
 using System.Text;
 using System.Net.Sockets;
 using System.Threading;
 using System.Net;namespace System.Net.Securate.TCP
 {
     public sealed class TCPClient
     {
         /// <summary>
         /// 收到消息事件
         /// </summary>
         public ReceiveBuffer ReceiveComtemplate;
         /// <summary>
         /// 主机断开连接事件
         /// </summary>
         public HostDisconnectionEvent HostDisconnectedComtelplate;
         private string _Address;
         /// <summary>
         /// 获取或设置连接地址
         /// </summary>
         public string Address
         {
             get { return _Address; }
             set { _Address = value; }
         }
         private int _Port;
         /// <summary>
         /// 获取或设置端口号
         /// </summary>
         public int Port
         {
             get { return _Port; }
             set { _Port = value; }
         }
         private Socket tcpClient;
         /// <summary>
         /// 获取连接状态
         /// </summary>
         public bool IsConnected
         {
             get {
                 if (tcpClient == null)
                     return false;
                 return tcpClient.Connected;
             }
         }
         /// <summary>
         /// 打开连接
         /// </summary>
         /// <returns></returns>
         public bool Start()
         {
             return Start(_Address, _Port);
         }
         /// <summary>
         /// 打开连接
         /// </summary>
         /// <param name="ip">连接地址</param>
         /// <param name="port">连接端口号</param>
         /// <returns></returns>
         public bool Start(string ip, int port)
         {
             try
             {
                 _Address = ip;
                 _Port = port;
                 tcpClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                 IPAddress ipaddress = IPAddress.Parse(_Address);
                 tcpClient.Connect(ipaddress, port);
                 if (tcpClient.Connected)
                 {
                     AsyncReceivedClient rc = new AsyncReceivedClient(Receive);
                     rc.BeginInvoke(tcpClient, null, null);
                 }
                 return tcpClient.Connected;
             }
             catch (Exception ex)
             {
                 return false;
             }
         }
         /// <summary>
         /// 接收消息
         /// </summary>
         /// <returns></returns>
         public void Receive(object o)
         {
             Socket s = o as Socket;
             bool IsConnected = true;
             while (s.Connected)
             {
                 try
                 {
                     int res = s.Available;
                     if (res > 0)
                     {
                         byte[] xxxx = new byte[res];
                         int nRead = s.Receive(xxxx);
                         byte[] buffer = new byte[nRead];
                         Array.Copy(xxxx, 0, buffer, 0, nRead);
                         if (ReceiveComtemplate != null)
                             ReceiveComtemplate(buffer);
                     }
                     else
                     {
                         try
                         {
                             Socket testSocket =
                                 new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                             testSocket.Connect(s.RemoteEndPoint);
                             if (!testSocket.Connected)
                             {
                                 Stop();
                                 IsConnected = false;
                                 goto EndReceive;
                             }
                             else
                             {
                                 testSocket.Shutdown(SocketShutdown.Both);
                                 testSocket.Close();
                             }
                         }
                         catch (Exception ex)
                         {
                             Stop();
                             IsConnected = false;
                             goto EndReceive;
                         }
                     }
                 }
                 catch (Exception ex)
                 {
                     Stop();
                     IsConnected = false;
                     goto EndReceive;
                 }
                 Thread.Sleep(100);
             }
             EndReceive:
             if (!IsConnected)
             {
                 if (HostDisconnectedComtelplate != null)
                     HostDisconnectedComtelplate();
             }
         }
         /// <summary>
         /// 发送消息
         /// </summary>
         /// <param name="buffer">发送的数据</param>
         public void Send(byte[] buffer)
         {
             try
             {
                 if (tcpClient.Connected)
                 {
                     tcpClient.Send(buffer);
                 }
             }
             catch { }
         }
         /// <summary>
         /// 停止
         /// </summary>
         public void Stop()
         {
             try
             {
                 //tcpClient.Client.Shutdown(SocketShutdown.Both);
                 //tcpClient.Close();
                 tcpClient.Shutdown(SocketShutdown.Both);
                 tcpClient.Close();
             }
             catch (Exception ex)
             { }
         }
     }
 }