C#网络编程TCP通信实例程序简单设计
采用自带 TcpClient和TcpListener设计一个Tcp通信的例子
只实现了TCP通信
通信程序截图:
压力测试服务端截图:
俩个客户端链接服务端测试截图:
服务端:
客户端
运行动态图
C#程序设计代码
BenXHSocket.dll主要代码设计
SocketObject类
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类
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类
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服务端监听类
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客户端类
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 }
服务端和客户端窗体应用程序主要方法设计实现
服务端窗体应用程序主要方法代码:
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 }
客户端窗体应用程序主要代码
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