• C#网络编程TCP通信实例程序简单设计


    2017-12-21 15:33:14 newbie_xymt 阅读数 1511

    采用自带 TcpClient和TcpListener设计一个Tcp通信的例子

    只实现了TCP通信

    通信程序截图:

    压力测试服务端截图:

    俩个客户端链接服务端测试截图:

    服务端:

    客户端

    运行动态图

    C#程序设计代码

    BenXHSocket.dll主要代码设计

    SocketObject类

    [csharp] view plain copy

    1. /***************************************************** 
    2.  * ProjectName:  BenXHSocket 
    3.  * Description: 
    4.  * ClassName:    SocketObject 
    5.  * CLRVersion:   4.0.30319.18408 
    6.  * Author:       JiYF 
    7.  * NameSpace:    BenXHSocket 
    8.  * MachineName:  JIYONGFEI 
    9.  * CreateTime:   2017/3/31 12:13:06 
    10.  * UpdatedTime:  2017/3/31 12:13:06 
    11. *****************************************************/  
    12. using System;  
    13. using System.Collections.Generic;  
    14. using System.Linq;  
    15. using System.Text;  
    16. using System.Net;  
    17.   
    18. namespace BenXHSocket  
    19. {  
    20.     /// <summary>  
    21.     /// Socket基础类  
    22.     /// </summary>  
    23.     public abstract class SocketObject  
    24.     {  
    25.         /// <summary>  
    26.         /// 初始化Socket方法  
    27.         /// </summary>  
    28.         /// <param name="ipAddress"></param>  
    29.         /// <param name="port"></param>  
    30.         public abstract void InitSocket(IPAddress ipAddress,int port);  
    31.         public abstract void InitSocket(string ipAddress,int port);  
    32.   
    33.         /// <summary>  
    34.         /// Socket启动方法  
    35.         /// </summary>  
    36.         public abstract void Start();  
    37.   
    38.         /// <summary>  
    39.         /// Sockdet停止方法  
    40.         /// </summary>  
    41.         public abstract void Stop();  
    42.   
    43.     }  
    44. }  

    sockets类

    [csharp] view plain copy

    1. /***************************************************** 
    2.  * ProjectName:  BenXHSocket 
    3.  * Description: 
    4.  * ClassName:    Sockets 
    5.  * CLRVersion:   4.0.30319.18408 
    6.  * Author:       JiYF 
    7.  * NameSpace:    BenXHSocket 
    8.  * MachineName:  JIYONGFEI 
    9.  * CreateTime:   2017/3/31 12:16:10 
    10.  * UpdatedTime:  2017/3/31 12:16:10 
    11. *****************************************************/  
    12. using System;  
    13. using System.Collections.Generic;  
    14. using System.Linq;  
    15. using System.Text;  
    16. using System.Net;  
    17. using System.Net.Sockets;  
    18.   
    19. namespace BenXHSocket  
    20. {  
    21.     public class Sockets  
    22.     {  
    23.         /// <summary>  
    24.         /// 接收缓冲区大小8k  
    25.         /// </summary>  
    26.         public byte[] RecBuffer = new byte[8 * 1024];   
    27.    
    28.         /// <summary>  
    29.         /// 发送缓冲区大小8k  
    30.         /// </summary>  
    31.         public byte[] SendBuffer = new byte[8 * 1024];  
    32.   
    33.         /// <summary>  
    34.         /// 异步接收后包的大小  
    35.         /// </summary>  
    36.         public int Offset { get;set;}  
    37.   
    38.         /// <summary>  
    39.         /// 当前IP地址,端口号  
    40.         /// </summary>  
    41.         public IPEndPoint Ip { get; set; }  
    42.         /// <summary>  
    43.         /// 客户端主通信程序  
    44.         /// </summary>  
    45.         public TcpClient Client { get; set; }  
    46.         /// <summary>  
    47.         /// 承载客户端Socket的网络流  
    48.         /// </summary>  
    49.         public NetworkStream nStream { get; set; }  
    50.   
    51.         /// <summary>  
    52.         /// 发生异常时不为null.  
    53.         /// </summary>  
    54.         public Exception ex { get; set; }  
    55.   
    56.         /// <summary>  
    57.         /// 新客户端标识.如果推送器发现此标识为true,那么认为是客户端上线  
    58.         /// 仅服务端有效  
    59.         /// </summary>  
    60.         public bool NewClientFlag { get; set; }  
    61.   
    62.         /// <summary>  
    63.         /// 客户端退出标识.如果服务端发现此标识为true,那么认为客户端下线  
    64.         /// 客户端接收此标识时,认为客户端异常.  
    65.         /// </summary>  
    66.         public bool ClientDispose { get; set; }  
    67.   
    68.         /// <summary>  
    69.         /// 空参构造  
    70.         /// </summary>  
    71.         public Sockets() { }  
    72.   
    73.         /// <summary>  
    74.         /// 构造函数  
    75.         /// </summary>  
    76.         /// <param name="ip">ip节点</param>  
    77.         /// <param name="client">TCPClient客户端</param>  
    78.         /// <param name="ns">NetworkStream </param>  
    79.         public Sockets(IPEndPoint ip,TcpClient client,NetworkStream ns)  
    80.         {  
    81.             this.Ip = ip;  
    82.             this.Client = client;  
    83.             this.nStream = ns;  
    84.         }  
    85.     }  
    86. }  

    SocketsHandler类[csharp] view plain copy

    1. /***************************************************** 
    2.  * ProjectName:  BenXHSocket 
    3.  * Description: 
    4.  * ClassName:    SocketsHandler 
    5.  * CLRVersion:   4.0.30319.18408 
    6.  * Author:       JiYF 
    7.  * NameSpace:    BenXHSocket 
    8.  * MachineName:  JIYONGFEI 
    9.  * CreateTime:   2017/3/31 13:42:48 
    10.  * UpdatedTime:  2017/3/31 13:42:48 
    11. *****************************************************/  
    12. using System;  
    13. using System.Collections.Generic;  
    14. using System.Linq;  
    15. using System.Text;  
    16.   
    17. namespace BenXHSocket  
    18. {  
    19.     /// <summary>  
    20.     /// 推送器  
    21.     /// </summary>  
    22.     /// <param name="sockets"></param>  
    23.     public delegate void PushSockets(Sockets sockets);  
    24.       
    25. }  

    BXHTcpServer类 tcp服务端监听类

    [csharp] view plain copy

    1. /***************************************************** 
    2.  * ProjectName:  BenXHSocket 
    3.  * Description: 
    4.  * ClassName:    TcpServer 
    5.  * CLRVersion:   4.0.30319.18408 
    6.  * Author:       JiYF 
    7.  * NameSpace:    BenXHSocket 
    8.  * MachineName:  JIYONGFEI 
    9.  * CreateTime:   2017/3/31 12:24:08 
    10.  * UpdatedTime:  2017/3/31 12:24:08 
    11. *****************************************************/  
    12. using System;  
    13. using System.Collections.Generic;  
    14. using System.Linq;  
    15. using System.Text;  
    16. using System.Threading;  
    17. using System.Net;  
    18. using System.Net.Sockets;  
    19.   
    20. namespace BenXHSocket  
    21. {  
    22.     /// <summary>  
    23.     /// TCPServer类 服务端程序  
    24.     /// </summary>  
    25.     public class BXHTcpServer:SocketObject  
    26.     {  
    27.         private bool IsStop = false;  
    28.         object obj = new object();  
    29.         public static PushSockets pushSockets;  
    30.   
    31.         /// <summary>  
    32.         /// 信号量  
    33.         /// </summary>  
    34.         private Semaphore semap = new Semaphore(5,5000);  
    35.   
    36.         /// <summary>  
    37.         /// 客户端列表集合  
    38.         /// </summary>  
    39.         public List<Sockets> ClientList = new List<Sockets>();  
    40.   
    41.         /// <summary>  
    42.         /// 服务端实例对象  
    43.         /// </summary>  
    44.         public TcpListener Listener;  
    45.   
    46.         /// <summary>  
    47.         /// 当前的ip地址  
    48.         /// </summary>  
    49.         private IPAddress IpAddress;  
    50.   
    51.         /// <summary>  
    52.         /// 初始化消息  
    53.         /// </summary>  
    54.         private string InitMsg = "JiYF笨小孩TCP服务端";  
    55.   
    56.         /// <summary>  
    57.         /// 监听的端口  
    58.         /// </summary>  
    59.         private int Port;  
    60.   
    61.         /// <summary>  
    62.         /// 当前ip和端口节点对象  
    63.         /// </summary>  
    64.         private IPEndPoint Ip;  
    65.   
    66.   
    67.         /// <summary>  
    68.         /// 初始化服务器对象  
    69.         /// </summary>  
    70.         /// <param name="ipAddress">IP地址</param>  
    71.         /// <param name="port">端口号</param>  
    72.         public override void InitSocket(IPAddress ipAddress, int port)  
    73.         {  
    74.             this.IpAddress = ipAddress;  
    75.             this.Port = port;  
    76.             this.Listener = new TcpListener(IpAddress,Port);  
    77.         }  
    78.   
    79.         /// <summary>  
    80.         /// 初始化服务器对象  
    81.         /// </summary>  
    82.         /// <param name="ipAddress"></param>  
    83.         /// <param name="port"></param>  
    84.         public override void InitSocket(string ipAddress, int port)  
    85.         {  
    86.             this.IpAddress = IPAddress.Parse(ipAddress);  
    87.             this.Port = port;  
    88.             this.Ip = new IPEndPoint(IpAddress,Port);  
    89.             this.Listener = new TcpListener(IpAddress,Port);  
    90.         }  
    91.   
    92.         /// <summary>  
    93.         /// 服务端启动监听,处理链接  
    94.         /// </summary>  
    95.         public override void Start()  
    96.         {  
    97.             try  
    98.             {   
    99.                 Listener.Start();  
    100.                 Thread Accth = new Thread(new ThreadStart(  
    101.                     delegate  
    102.                     {  
    103.                         while(true)  
    104.                         {  
    105.                             if(IsStop != false)  
    106.                             {  
    107.                                 break;  
    108.                             }  
    109.                             this.GetAcceptTcpClient();  
    110.                             Thread.Sleep(1);  
    111.                         }  
    112.                     }  
    113.                     ));  
    114.                 Accth.Start();  
    115.             }  
    116.             catch(SocketException skex)  
    117.             {  
    118.                 Sockets sks = new Sockets();  
    119.                 sks.ex = skex;  
    120.                 pushSockets.Invoke(sks);  
    121.             }  
    122.         }  
    123.   
    124.         /// <summary>  
    125.         /// 获取处理新的链接请求  
    126.         /// </summary>  
    127.         private void GetAcceptTcpClient()  
    128.         {  
    129.             try  
    130.             {   
    131.                 if(Listener.Pending())  
    132.                 {  
    133.                     semap.WaitOne();  
    134.                     //接收到挂起的客户端请求链接  
    135.                     TcpClient tcpClient = Listener.AcceptTcpClient();  
    136.   
    137.                     //维护处理客户端队列  
    138.                     Socket socket = tcpClient.Client;  
    139.                     NetworkStream stream = new NetworkStream(socket,true);  
    140.                     Sockets sks = new Sockets(tcpClient.Client.RemoteEndPoint as IPEndPoint,tcpClient,stream);  
    141.                     sks.NewClientFlag = true;  
    142.   
    143.                     //推送新的客户端连接信息  
    144.                     pushSockets.Invoke(sks);  
    145.   
    146.                     //客户端异步接收数据  
    147.                     sks.nStream.BeginRead(sks.RecBuffer,0,sks.RecBuffer.Length,new AsyncCallback(EndReader),sks);  
    148.                       
    149.                     //加入客户端队列  
    150.                     this.AddClientList(sks);  
    151.   
    152.                     //链接成功后主动向客户端发送一条消息  
    153.                     if(stream.CanWrite)  
    154.                     {  
    155.                         byte[] buffer = Encoding.UTF8.GetBytes(this.InitMsg);  
    156.                         stream.Write(buffer, 0, buffer.Length);  
    157.                     }  
    158.                     semap.Release();  
    159.                 }  
    160.             }  
    161.             catch  
    162.             {  
    163.                 return;  
    164.             }  
    165.         }  
    166.   
    167.         /// <summary>  
    168.         /// 异步接收发送的的信息  
    169.         /// </summary>  
    170.         /// <param name="ir"></param>  
    171.         private void EndReader(IAsyncResult ir)  
    172.         {  
    173.             Sockets sks = ir.AsyncState as Sockets;  
    174.             if (sks != null && Listener != null)  
    175.             {  
    176.                 try  
    177.                 {  
    178.                     if (sks.NewClientFlag || sks.Offset != 0)  
    179.                     {  
    180.                         sks.NewClientFlag = false;  
    181.                         sks.Offset = sks.nStream.EndRead(ir);  
    182.                         //推送到UI  
    183.                         pushSockets.Invoke(sks);  
    184.                         sks.nStream.BeginRead(sks.RecBuffer,0,sks.RecBuffer.Length,new AsyncCallback(EndReader),sks);  
    185.                     }  
    186.                 }  
    187.                 catch(Exception skex)  
    188.                 {  
    189.                     lock (obj)  
    190.                     {  
    191.                         ClientList.Remove(sks);  
    192.                         Sockets sk = sks;  
    193.                         //标记客户端退出程序  
    194.                         sk.ClientDispose = true;  
    195.                         sk.ex = skex;  
    196.                         //推送至UI  
    197.                         pushSockets.Invoke(sks);  
    198.                     }  
    199.                 }  
    200.             }  
    201.         }  
    202.   
    203.         /// <summary>  
    204.         /// 客户端加入队列  
    205.         /// </summary>  
    206.         /// <param name="sk"></param>  
    207.         private void AddClientList(Sockets sk)  
    208.         {  
    209.             lock (obj)  
    210.             {  
    211.                 Sockets sockets = ClientList.Find(o => { return o.Ip == sk.Ip; });  
    212.                 if (sockets == null)  
    213.                 {  
    214.                     ClientList.Add(sk);  
    215.                 }  
    216.                 else  
    217.                 {  
    218.                     ClientList.Remove(sockets);  
    219.                     ClientList.Add(sk);  
    220.                 }  
    221.             }  
    222.         }  
    223.   
    224.         /// <summary>  
    225.         /// 服务端停止监听  
    226.         /// </summary>  
    227.         public override void Stop()  
    228.         {  
    229.             if (Listener != null)  
    230.             {  
    231.                 Listener.Stop();  
    232.                 Listener = null;  
    233.                 IsStop = true;  
    234.                 pushSockets = null;  
    235.             }  
    236.         }  
    237.   
    238.         /// <summary>  
    239.         /// 向所有在线客户端发送消息  
    240.         /// </summary>  
    241.         /// <param name="SendData">消息内容</param>  
    242.         public void SendToAll(string SendData)  
    243.         {  
    244.             for (int i = 0; i < ClientList.Count; i++)  
    245.             {  
    246.                 SendToClient(ClientList[i].Ip, SendData);  
    247.             }  
    248.         }  
    249.   
    250.         /// <summary>  
    251.         /// 向单独的一个客户端发送消息  
    252.         /// </summary>  
    253.         /// <param name="ip"></param>  
    254.         /// <param name="SendData"></param>  
    255.         public void SendToClient(IPEndPoint ip,string SendData)  
    256.         {  
    257.             try  
    258.             {  
    259.                 Sockets sks = ClientList.Find(o => { return o.Ip == ip; });  
    260.                 if(sks == null || !sks.Client.Connected)  
    261.                 {  
    262.                     Sockets ks = new Sockets();  
    263.                     //标识客户端下线  
    264.                     sks.ClientDispose = true;  
    265.                     sks.ex = new Exception("客户端没有连接");  
    266.                     pushSockets.Invoke(sks);  
    267.                 }  
    268.                 if(sks.Client.Connected)  
    269.                 {  
    270.                      //获取当前流进行写入.  
    271.                         NetworkStream nStream = sks.nStream;  
    272.                         if (nStream.CanWrite)  
    273.                         {  
    274.                             byte[] buffer = Encoding.UTF8.GetBytes(SendData);  
    275.                             nStream.Write(buffer, 0, buffer.Length);  
    276.                         }  
    277.                         else  
    278.                         {  
    279.                             //避免流被关闭,重新从对象中获取流  
    280.                             nStream = sks.Client.GetStream();  
    281.                             if (nStream.CanWrite)  
    282.                             {  
    283.                                 byte[] buffer = Encoding.UTF8.GetBytes(SendData);  
    284.                                 nStream.Write(buffer, 0, buffer.Length);  
    285.                             }  
    286.                             else  
    287.                             {  
    288.                                 //如果还是无法写入,那么认为客户端中断连接.  
    289.                                 ClientList.Remove(sks);  
    290.                                 Sockets ks = new Sockets();  
    291.                                 sks.ClientDispose = true;//如果出现异常,标识客户端下线  
    292.                                 sks.ex = new Exception("客户端无连接");  
    293.                                 pushSockets.Invoke(sks);//推送至UI  
    294.   
    295.                             }  
    296.                         }   
    297.                 }  
    298.             }  
    299.             catch(Exception skex)  
    300.             {   
    301.                 Sockets sks = new Sockets();  
    302.                     sks.ClientDispose = true;//如果出现异常,标识客户端退出  
    303.                     sks.ex = skex;  
    304.                     pushSockets.Invoke(sks);//推送至UI  
    305.             }  
    306.         }  
    307.     }  
    308. }  

    BXHTcpClient 类 Tcp客户端类

    [csharp] view plain copy

    1. /***************************************************** 
    2.  * ProjectName:  BenXHSocket 
    3.  * Description: 
    4.  * ClassName:    BxhTcpClient 
    5.  * CLRVersion:   4.0.30319.42000 
    6.  * Author:       JiYF 
    7.  * NameSpace:    BenXHSocket 
    8.  * MachineName:  JIYF_PC 
    9.  * CreateTime:   2017/3/31 20:31:48 
    10.  * UpdatedTime:  2017/3/31 20:31:48 
    11. *****************************************************/  
    12. using System;  
    13. using System.Collections.Generic;  
    14. using System.Linq;  
    15. using System.Text;  
    16. using System.Net;  
    17. using System.Net.Sockets;  
    18. using System.Threading;  
    19.   
    20. namespace BenXHSocket  
    21. {  
    22.     public class BXHTcpClient : SocketObject  
    23.     {  
    24.             bool IsClose = false;  
    25.   
    26.             /// <summary>  
    27.             /// 当前管理对象  
    28.             /// </summary>  
    29.             Sockets sk;  
    30.   
    31.             /// <summary>  
    32.             /// 客户端  
    33.             /// </summary>  
    34.            public TcpClient client;  
    35.   
    36.             /// <summary>  
    37.             /// 当前连接服务端地址  
    38.             /// </summary>  
    39.             IPAddress Ipaddress;  
    40.   
    41.             /// <summary>  
    42.             /// 当前连接服务端端口号  
    43.             /// </summary>  
    44.             int Port;  
    45.   
    46.             /// <summary>  
    47.             /// 服务端IP+端口  
    48.             /// </summary>  
    49.             IPEndPoint ip;  
    50.   
    51.             /// <summary>  
    52.             /// 发送与接收使用的流  
    53.             /// </summary>  
    54.             NetworkStream nStream;  
    55.           
    56.             
    57.   
    58.             /// <summary>  
    59.             /// 初始化Socket  
    60.             /// </summary>  
    61.             /// <param name="ipaddress"></param>  
    62.             /// <param name="port"></param>  
    63.             public override void InitSocket(string ipaddress, int port)  
    64.             {  
    65.                 Ipaddress = IPAddress.Parse(ipaddress);  
    66.                 Port = port;  
    67.                 ip = new IPEndPoint(Ipaddress, Port);  
    68.                 client = new TcpClient();  
    69.             }  
    70.   
    71.             public static PushSockets pushSockets;  
    72.             public void SendData(string SendData)  
    73.             {  
    74.                 try  
    75.                 {  
    76.   
    77.                     if (client == null || !client.Connected)  
    78.                     {  
    79.                         Sockets sks = new Sockets();  
    80.                         sks.ex = new Exception("客户端无连接..");  
    81.                         sks.ClientDispose = true;  
    82.                           
    83.                         pushSockets.Invoke(sks);//推送至UI   
    84.                     }  
    85.                     if (client.Connected) //如果连接则发送  
    86.                     {  
    87.                         if (nStream == null)  
    88.                         {  
    89.                             nStream = client.GetStream();  
    90.                         }  
    91.                         byte[] buffer = Encoding.UTF8.GetBytes(SendData);  
    92.                         nStream.Write(buffer, 0, buffer.Length);  
    93.                     }  
    94.                 }  
    95.                 catch (Exception skex)  
    96.                 {  
    97.                     Sockets sks = new Sockets();  
    98.                     sks.ex = skex;  
    99.                     sks.ClientDispose = true;  
    100.                     pushSockets.Invoke(sks);//推送至UI  
    101.                 }  
    102.             }  
    103.             /// <summary>  
    104.             /// 初始化Socket  
    105.             /// </summary>  
    106.             /// <param name="ipaddress"></param>  
    107.             /// <param name="port"></param>  
    108.             public override void InitSocket(IPAddress ipaddress, int port)  
    109.             {  
    110.                 Ipaddress = ipaddress;  
    111.                 Port = port;  
    112.                 ip = new IPEndPoint(Ipaddress, Port);  
    113.                 client = new TcpClient();  
    114.             }  
    115.             private void Connect()  
    116.             {  
    117.                 client.Connect(ip);  
    118.                 nStream = new NetworkStream(client.Client, true);  
    119.                 sk = new Sockets(ip, client, nStream);  
    120.                 sk.nStream.BeginRead(sk.RecBuffer, 0, sk.RecBuffer.Length, new AsyncCallback(EndReader), sk);  
    121.             }  
    122.             private void EndReader(IAsyncResult ir)  
    123.             {  
    124.   
    125.                 Sockets s = ir.AsyncState as Sockets;  
    126.                 try  
    127.                 {  
    128.                     if (s != null)  
    129.                     {  
    130.   
    131.                         if (IsClose && client == null)  
    132.                         {  
    133.                             sk.nStream.Close();  
    134.                             sk.nStream.Dispose();  
    135.                             return;  
    136.                         }  
    137.                         s.Offset = s.nStream.EndRead(ir);  
    138.                         pushSockets.Invoke(s);//推送至UI  
    139.                         sk.nStream.BeginRead(sk.RecBuffer, 0, sk.RecBuffer.Length, new AsyncCallback(EndReader), sk);  
    140.                     }  
    141.                 }  
    142.                 catch (Exception skex)  
    143.                 {  
    144.                     Sockets sks = s;  
    145.                     sks.ex = skex;  
    146.                     sks.ClientDispose = true;  
    147.                     pushSockets.Invoke(sks);//推送至UI  
    148.   
    149.                 }  
    150.   
    151.             }  
    152.             /// <summary>  
    153.             /// 重写Start方法,其实就是连接服务端  
    154.             /// </summary>  
    155.             public override void Start()  
    156.             {  
    157.                 Connect();  
    158.             }  
    159.             public override void Stop()  
    160.             {  
    161.                 Sockets sks = new Sockets();  
    162.                 if (client != null)  
    163.                 {  
    164.                     client.Client.Shutdown(SocketShutdown.Both);  
    165.                     Thread.Sleep(10);  
    166.                     client.Close();  
    167.                     IsClose = true;  
    168.                     client = null;  
    169.                 }  
    170.                 else  
    171.                 {  
    172.                     sks.ex = new Exception("客户端没有初始化.!");  
    173.                 }  
    174.                 pushSockets.Invoke(sks);//推送至UI  
    175.             }  
    176.   
    177.         }  
    178. }  

    服务端和客户端窗体应用程序主要方法设计实现

    服务端窗体应用程序主要方法代码:

    [csharp] view plain copy

    1. using System;  
    2. using System.Collections.Generic;  
    3. using System.ComponentModel;  
    4. using System.Data;  
    5. using System.Drawing;  
    6. using System.Linq;  
    7. using System.Text;  
    8. using System.Windows.Forms;  
    9. using System.Configuration;  
    10. using System.Net;  
    11. using BenXHSocket;  
    12. using System.Threading;  
    13.   
    14. namespace BenXHSocketTcpServer  
    15. {  
    16.     public partial class FrmTCPServer : Form  
    17.     {  
    18.         private static string serverIP;  
    19.         private static int port;  
    20.         object obj = new object();  
    21.         private int sendInt = 0;  
    22.         private static Dictionary<TreeNode, IPEndPoint> DicTreeIPEndPoint = new Dictionary<TreeNode, IPEndPoint>();  
    23.   
    24.         public FrmTCPServer()  
    25.         {  
    26.             InitializeComponent();  
    27.               
    28.             serverIP = ConfigurationManager.AppSettings["ServerIP"];  
    29.             port = int.Parse(ConfigurationManager.AppSettings["ServerPort"]);  
    30.             Control.CheckForIllegalCrossThreadCalls = false;  
    31.             init();  
    32.         }  
    33.   
    34.         private void init()  
    35.         {  
    36.             treeViewClientList.Nodes.Clear();  
    37.             TreeNode tn = new TreeNode();  
    38.             tn.Name = "ClientList";  
    39.             tn.Text = "客户端列表";  
    40.             tn.ImageIndex = 0;  
    41.             tn.ContextMenuStrip = contextMenuStripClientAll;  
    42.             treeViewClientList.Nodes.Add(tn);  
    43.             DicTreeIPEndPoint.Clear();  
    44.   
    45.             //自已绘制    
    46.             this.treeViewClientList.DrawMode = TreeViewDrawMode.OwnerDrawText;  
    47.             this.treeViewClientList.DrawNode += new DrawTreeNodeEventHandler(treeViewClientList_DrawNode);  
    48.         }  
    49.   
    50.         private BenXHSocket.BXHTcpServer tcpServer;  
    51.   
    52.   
    53.         /// <summary>  
    54.         /// 绘制颜色  
    55.         /// </summary>  
    56.         /// <param name="sender"></param>  
    57.         /// <param name="e"></param>  
    58.         private void treeViewClientList_DrawNode(object sender, DrawTreeNodeEventArgs e)  
    59.         {  
    60.             e.DrawDefault = true; //我这里用默认颜色即可,只需要在TreeView失去焦点时选中节点仍然突显    
    61.             return;  
    62.             //or  自定义颜色    
    63.             if ((e.State & TreeNodeStates.Selected) != 0)  
    64.             {  
    65.                 //演示为绿底白字    
    66.                 e.Graphics.FillRectangle(Brushes.DarkBlue, e.Node.Bounds);  
    67.   
    68.                 Font nodeFont = e.Node.NodeFont;  
    69.                 if (nodeFont == null) nodeFont = ((TreeView)sender).Font;  
    70.                 e.Graphics.DrawString(e.Node.Text, nodeFont, Brushes.White, Rectangle.Inflate(e.Bounds, 2, 0));  
    71.             }  
    72.             else  
    73.             {  
    74.                 e.DrawDefault = true;  
    75.             }  
    76.   
    77.             if ((e.State & TreeNodeStates.Focused) != 0)  
    78.             {  
    79.                 using (Pen focusPen = new Pen(Color.Black))  
    80.                 {  
    81.                     focusPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;  
    82.                     Rectangle focusBounds = e.Node.Bounds;  
    83.                     focusBounds.Size = new Size(focusBounds.Width - 1,  
    84.                     focusBounds.Height - 1);  
    85.                     e.Graphics.DrawRectangle(focusPen, focusBounds);  
    86.                 }  
    87.             }  
    88.   
    89.         }    
    90.   
    91.         /// <summary>  
    92.         /// 开启服务  
    93.         /// </summary>  
    94.         /// <param name="sender"></param>  
    95.         /// <param name="e"></param>  
    96.         private void StartServerToolStripMenuItem_Click(object sender, EventArgs e)  
    97.         {  
    98.             try  
    99.             {  
    100.                 if (serverIP != null && serverIP != "" && port != null && port >= 0)  
    101.                 {  
    102.                     tcpServer.InitSocket(IPAddress.Parse(serverIP), port);  
    103.                     tcpServer.Start();  
    104.                     listBoxServerInfo.Items.Add(string.Format("{0}服务端程序监听启动成功!监听:{1}:{2}",DateTime.Now.ToString(), serverIP, port.ToString()));  
    105.                     StartServerToolStripMenuItem.Enabled = false;  
    106.                 }  
    107.   
    108.                   
    109.             }  
    110.             catch(Exception ex)  
    111.             {  
    112.                 listBoxServerInfo.Items.Add(string.Format("服务器启动失败!原因:{0}",ex.Message));  
    113.                 StartServerToolStripMenuItem.Enabled = true;  
    114.             }  
    115.         }  
    116.   
    117.         /// <summary>  
    118.         /// 停止服务监听  
    119.         /// </summary>  
    120.         /// <param name="sender"></param>  
    121.         /// <param name="e"></param>  
    122.         private void StopServerToolStripMenuItem_Click(object sender, EventArgs e)  
    123.         {  
    124.             tcpServer.Stop();  
    125.             listBoxServerInfo.Items.Add("服务器程序停止成功!");  
    126.             StartServerToolStripMenuItem.Enabled = true;  
    127.              
    128.         }  
    129.   
    130.         private void FrmTCPServer_Load(object sender, EventArgs e)  
    131.         {  
    132.             if(tcpServer ==null)  
    133.             listBoxServerInfo.Items.Add(string.Format("服务端监听程序尚未开启!{0}:{1}",serverIP,port));  
    134.             treeViewClientList.ExpandAll();  
    135.             BXHTcpServer.pushSockets = new PushSockets(Rev);  
    136.             tcpServer = new BXHTcpServer();  
    137.         }  
    138.   
    139.         /// <summary>  
    140.         /// 处理接收到客户端的请求和数据  
    141.         /// </summary>  
    142.         /// <param name="sks"></param>  
    143.         private void Rev(BenXHSocket.Sockets sks)  
    144.         {  
    145.             this.Invoke(new ThreadStart(  
    146.                 delegate  
    147.                 {  
    148.                     if (treeViewClientList.Nodes[0] != null)  
    149.                     {   
    150.                           
    151.                     }  
    152.   
    153.                     if (sks.ex != null)  
    154.                     {  
    155.                         if (sks.ClientDispose)  
    156.                         {  
    157.                             listBoxServerInfo.Items.Add(string.Format("{0}客户端:{1}下线!",DateTime.Now.ToString(), sks.Ip));  
    158.                             if (treeViewClientList.Nodes[0].Nodes.ContainsKey(sks.Ip.ToString()))  
    159.                             {  
    160.                                 if (DicTreeIPEndPoint.Count != 0)  
    161.                                 {  
    162.                                     removTreeIPEndPoint(sks.Ip);  
    163.                                     treeViewClientList.Nodes[0].Nodes.RemoveByKey(sks.Ip.ToString());  
    164.   
    165.                                     toolStripStatusLabelClientNum.Text = (int.Parse(toolStripStatusLabelClientNum.Text) - 1).ToString();//treeViewClientList.Nodes[0].Nodes.Count.ToString();  
    166.                              
    167.                                 }  
    168.                                  
    169.                                }  
    170.                         }  
    171.                         listBoxServerInfo.Items.Add(sks.ex.Message);  
    172.                     }  
    173.                     else  
    174.                     {  
    175.                         if (sks.NewClientFlag)  
    176.                         {  
    177.                             listBoxServerInfo.Items.Add(string.Format("{0}新的客户端:{0}链接成功",DateTime.Now.ToString(), sks.Ip));  
    178.                               
    179.                             TreeNode tn = new TreeNode();  
    180.                             tn.Name = sks.Ip.ToString();  
    181.                             tn.Text = sks.Ip.ToString();  
    182.                             tn.ContextMenuStrip = contextMenuStripClientSingle;  
    183.                             tn.Tag = "客户端";  
    184.                             tn.ImageIndex = 1;  
    185.   
    186.                             treeViewClientList.Nodes[0].Nodes.Add(tn);  
    187.   
    188.                             //treeview节点和IPEndPoint绑定  
    189.                             DicTreeIPEndPoint.Add(tn,sks.Ip);  
    190.   
    191.                             if (treeViewClientList.Nodes[0].Nodes.Count > 0)  
    192.                             {  
    193.                                 treeViewClientList.ExpandAll();  
    194.                             }  
    195.                             toolStripStatusLabelClientNum.Text = (int.Parse(toolStripStatusLabelClientNum.Text)+1).ToString();  
    196.                         }  
    197.                         else if (sks.Offset == 0)  
    198.                         {  
    199.                             listBoxServerInfo.Items.Add(string.Format("{0}客户端:{1}下线.!",DateTime.Now.ToString(), sks.Ip));  
    200.                             if (treeViewClientList.Nodes[0].Nodes.ContainsKey(sks.Ip.ToString()))  
    201.                             {  
    202.                                 if (DicTreeIPEndPoint.Count != 0)  
    203.                                 {  
    204.                                     removTreeIPEndPoint(sks.Ip);  
    205.                                     treeViewClientList.Nodes[0].Nodes.RemoveByKey(sks.Ip.ToString());  
    206.   
    207.                                     toolStripStatusLabelClientNum.Text = (int.Parse(toolStripStatusLabelClientNum.Text) - 1).ToString();  
    208.                               
    209.                                 }  
    210.                             }  
    211.                         }  
    212.                         else  
    213.                         {  
    214.                             byte[] buffer = new byte[sks.Offset];  
    215.                             Array.Copy(sks.RecBuffer, buffer, sks.Offset);  
    216.                             string str = Encoding.UTF8.GetString(buffer);  
    217.                             listBox1.Items.Add(string.Format("{0}客户端{1}发来消息:{2}",DateTime.Now.ToString(), sks.Ip, str));  
    218.                         }  
    219.                     }  
    220.                 }  
    221.                 )  
    222.                 );  
    223.         }  
    224.   
    225.         /// <summary>  
    226.         /// 关闭程序钱停止服务器实例  
    227.         /// </summary>  
    228.         /// <param name="sender"></param>  
    229.         /// <param name="e"></param>  
    230.         private void FrmTCPServer_FormClosing(object sender, FormClosingEventArgs e)  
    231.         {  
    232.             tcpServer.Stop();  
    233.         }  
    234.   
    235.         private void treeViewClientList_AfterSelect(object sender, TreeViewEventArgs e)  
    236.         {  
    237.             //  
    238.         }  
    239.   
    240.         private void treeViewClientList_MouseClick(object sender, MouseEventArgs e)  
    241.         {  
    242.             if (e.Button == MouseButtons.Right)  
    243.             {  
    244.                 treeViewClientList.Focus();  
    245.                 treeViewClientList.SelectedNode = treeViewClientList.GetNodeAt(e.X,e.Y);  
    246.             }  
    247.   
    248.         }  
    249.   
    250.   
    251.         private void toolStripMenuSendSingle_Click(object sender, EventArgs e)  
    252.         {  
    253.             if (treeViewClientList.SelectedNode != null)  
    254.             {  
    255.                 tcpServer.SendToClient(DicTreeIPEndPoint[treeViewClientList.SelectedNode], string.Format("服务端单个消息...{0}", sendInt.ToString()));  
    256.                 sendInt++;  
    257.             }  
    258.         }  
    259.   
    260.         private void toolStripMenuSendAll_Click(object sender, EventArgs e)  
    261.         {  
    262.             tcpServer.SendToAll("服务端全部发送消息..." + sendInt);  
    263.             sendInt++;  
    264.         }  
    265.   
    266.         private void removTreeIPEndPoint(IPEndPoint ipendPoint)  
    267.         {  
    268.   
    269.             if (DicTreeIPEndPoint.Count <= 0) return;  
    270.             //foreach遍历Dictionary时候不能对字典进行Remove  
    271.             TreeNode[] keys = new TreeNode[DicTreeIPEndPoint.Count];  
    272.             DicTreeIPEndPoint.Keys.CopyTo(keys,0);  
    273.             lock (obj)  
    274.             {  
    275.                 foreach (TreeNode item in keys)  
    276.                 {  
    277.                     if (DicTreeIPEndPoint[item] == ipendPoint)  
    278.                     {  
    279.                         DicTreeIPEndPoint.Remove(item);  
    280.                     }  
    281.                 }  
    282.             }  
    283.         }  
    284.   
    285.     }  
    286. }  

    客户端窗体应用程序主要代码

    [csharp] view plain copy

    1. using System;  
    2. using System.Collections.Generic;  
    3. using System.ComponentModel;  
    4. using System.Data;  
    5. using System.Drawing;  
    6. using System.Linq;  
    7. using System.Text;  
    8. using System.Windows.Forms;  
    9. using System.Net;  
    10. using System.Net.Sockets;  
    11. using BenXHSocket;  
    12. using System.Threading;  
    13.   
    14. namespace BenXHSocketClient  
    15. {  
    16.     public partial class FrmTCPClient : Form  
    17.     {  
    18.         BXHTcpClient tcpClient;  
    19.           
    20.         string ip = string.Empty;  
    21.         string port = string.Empty;  
    22.         private int sendInt = 0;  
    23.         public FrmTCPClient()  
    24.         {  
    25.             InitializeComponent();  
    26.             Control.CheckForIllegalCrossThreadCalls = false;  
    27.         }  
    28.   
    29.         private void btnConnServer_Click(object sender, EventArgs e)  
    30.         {  
    31.             try  
    32.             {  
    33.                 this.ip = txtServerIP.Text.Trim();  
    34.                 this.port = txtServerPort.Text.Trim();  
    35.   
    36.                 tcpClient.InitSocket(ip, int.Parse(port));  
    37.                 tcpClient.Start();  
    38.                 listBoxStates.Items.Add("连接成功!");  
    39.                 btnConnServer.Enabled = false;  
    40.   
    41.             }  
    42.             catch (Exception ex)  
    43.             {  
    44.   
    45.                 listBoxStates.Items.Add(string.Format("连接失败!原因:{0}", ex.Message));  
    46.                 btnConnServer.Enabled = true;  
    47.             }  
    48.         }  
    49.   
    50.         private void FrmTCPClient_Load(object sender, EventArgs e)  
    51.         {  
    52.             //客户端如何处理异常等信息参照服务端  
    53.            
    54.             BXHTcpClient.pushSockets = new PushSockets(Rec);  
    55.   
    56.             tcpClient = new BXHTcpClient();  
    57.             this.ip = txtServerIP.Text.Trim();  
    58.             this.port = txtServerPort.Text.Trim();  
    59.             
    60.         }  
    61.   
    62.         /// <summary>  
    63.         /// 处理推送过来的消息  
    64.         /// </summary>  
    65.         /// <param name="rec"></param>  
    66.         private void Rec(BenXHSocket.Sockets sks)  
    67.         {  
    68.             this.Invoke(new ThreadStart(delegate  
    69.             {  
    70.                 if (listBoxText.Items.Count > 1000)  
    71.                 {  
    72.                     listBoxText.Items.Clear();  
    73.                 }  
    74.                 if (sks.ex != null)  
    75.                 {  
    76.                     if (sks.ClientDispose == true)  
    77.                     {  
    78.                         //由于未知原因引发异常.导致客户端下线.   比如网络故障.或服务器断开连接.  
    79.                         listBoxStates.Items.Add(string.Format("客户端下线.!"));  
    80.                     }  
    81.                     listBoxStates.Items.Add(string.Format("异常消息:{0}", sks.ex));  
    82.                 }  
    83.                 else if (sks.Offset == 0)  
    84.                 {  
    85.                     //客户端主动下线  
    86.                     listBoxStates.Items.Add(string.Format("客户端下线.!"));  
    87.                 }  
    88.                 else  
    89.                 {  
    90.                     byte[] buffer = new byte[sks.Offset];  
    91.                     Array.Copy(sks.RecBuffer, buffer, sks.Offset);  
    92.                     string str = Encoding.UTF8.GetString(buffer);  
    93.                     listBoxText.Items.Add(string.Format("服务端{0}发来消息:{1}", sks.Ip, str));  
    94.                 }  
    95.             }));  
    96.         }  
    97.   
    98.         private void btnDisConn_Click(object sender, EventArgs e)  
    99.         {  
    100.             tcpClient.Stop();  
    101.             btnConnServer.Enabled = true;  
    102.         }  
    103.   
    104.         private void btnSendData_Click(object sender, EventArgs e)  
    105.         {  
    106.             tcpClient.SendData("客户端消息!" + sendInt);  
    107.             sendInt++;  
    108.               
    109.         }  
    110.   
    111.         private void btnConnTest_Click(object sender, EventArgs e)  
    112.         {  
    113.             ThreadPool.QueueUserWorkItem(o =>  
    114.             {  
    115.                 for (int i = 0; i < 100; i++)  
    116.                 {  
    117.                     BenXHSocket.BXHTcpClient clientx= new  BenXHSocket.BXHTcpClient();//初始化类库    
    118.                     clientx.InitSocket(ip, int.Parse(port));  
    119.                     clientx.Start();  
    120.                 }  
    121.                 MessageBox.Show("完成.!");  
    122.             });  
    123.         }  
    124.   
    125.   
    126.     }  
    127. }  

    运行程序下载:

    BenXHSocket程序下载 

    源代码工程文件下载

    内容:

    BenXHSocket.dll      主要程序动态库

    BenXHSocketClient.exe   客户端应用程序

    BenXHSocketTcpServer.exe  服务端应用程序

    BenXHSocketTcpServer.exe.config  服务端应用程序配置文件

    其中:BenXHSocketTcpServer.exe.config为配置文件,可以设置监听的ip地址和端口号,默认ip地址:127.0.0.1 默认的端口号:4455

     

  • 相关阅读:
    php中 include 、include_once、require、require_once4个语言结构的含义和区别
    PHP yield 分析,以及协程的实现,超详细版(上)
    wordpress里的bloginfo()与get_bloginfo()
    CSS定位中“父相子绝”
    Apache 的 httpd.conf 详解
    apache的<directory>语句以及属性的含义
    你必须了解的Session的本质(PHP)
    Linux常用命令
    vmware中配置CentOS
    程序员可能会遇到的一些名词
  • 原文地址:https://www.cnblogs.com/grj001/p/12223459.html
Copyright © 2020-2023  润新知