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