文章系列目录
C#网络编程系列文章(一)之Socket实现异步TCP服务器
C#网络编程系列文章(二)之Socket实现同步TCP服务器
C#网络编程系列文章(三)之TcpListener实现异步TCP服务器
C#网络编程系列文章(五)之Socket实现异步UDP服务器
C#网络编程系列文章(六)之Socket实现同步UDP服务器
C#网络编程系列文章(七)之UdpClient实现异步UDP服务器
C#网络编程系列文章(八)之UdpClient实现同步UDP服务器
参考路径:
https://blog.csdn.net/zhujunxxxxx/article/details/44258719
代码下载地址
http://download.csdn.net/detail/zhujunxxxxx/8510991
本文介绍
TcpListener 类提供一些简单方法,用于在阻止同步模式下侦听和接受传入连接请求。 可使用 TcpClient 或 Socket 来连接 TcpListener。 可使用 IPEndPoint、本地 IP 地址及端口号或者仅使用端口号,来创建 TcpListener。 可以将本地 IP 地址指定为 Any,将本地端口号指定为 0(如果希望基础服务提供程序为您分配这些值)。 如果您选择这样做,可在连接套接字后使用 LocalEndpoint 属性来标识已指定的信息。使用 Start 方法,可开始侦听传入的连接请求。
Start 将对传入连接进行排队,直至您调用 Stop 方法或它已经完成 MaxConnections 排队为止。 可使用 AcceptSocket 或 AcceptTcpClient 从传入连接请求队列提取连接。 这两种方法将阻止。 如果要避免阻止,可首先使用 Pending 方法来确定队列中是否有可用的连接请求。
虽然TcpListener已经封装的比较不错了,我们于是就使用它在构造一个比较不错的同步TCP服务器,这里依然和前两章一样,给出服务器中的代码,代码中注释很详细,我也会给出相关的封装类。
TcpListener同步TCP服务器:
1 using System; 2 3 using System.Collections.Generic; 4 5 using System.Linq; 6 7 using System.Text; 8 9 using System.Net.Sockets; 10 11 using System.Net; 12 13 using System.Threading; 14 15 16 17 namespace NetFrame.Net.TCP.Listener.Synchronous 18 19 { 20 21 /// <summary> 22 23 /// TcpListener实现同步TCP服务器 24 25 /// </summary> 26 27 public class TCPServer 28 29 { 30 31 #region Fields 32 33 /// <summary> 34 35 /// 服务器程序允许的最大客户端连接数 36 37 /// </summary> 38 39 private int _maxClient; 40 41 42 43 /// <summary> 44 45 /// 当前的连接的客户端数 46 47 /// </summary> 48 49 private int _clientCount; 50 51 52 53 /// <summary> 54 55 /// 服务器使用的异步TcpListener 56 57 /// </summary> 58 59 private TcpListener _listener; 60 61 62 63 /// <summary> 64 65 /// 客户端会话列表 66 67 /// </summary> 68 69 private List<TCPClientHandle> _clients; 70 71 72 73 private bool disposed = false; 74 75 76 77 #endregion 78 79 80 81 #region Properties 82 83 84 85 /// <summary> 86 87 /// 服务器是否正在运行 88 89 /// </summary> 90 91 public bool IsRunning { get; private set; } 92 93 /// <summary> 94 95 /// 监听的IP地址 96 97 /// </summary> 98 99 public IPAddress Address { get; private set; } 100 101 /// <summary> 102 103 /// 监听的端口 104 105 /// </summary> 106 107 public int Port { get; private set; } 108 109 /// <summary> 110 111 /// 通信使用的编码 112 113 /// </summary> 114 115 public Encoding Encoding { get; set; } 116 117 118 119 #endregion 120 121 122 123 #region 构造器 124 125 /// <summary> 126 127 /// 同步TCP服务器 128 129 /// </summary> 130 131 /// <param name="listenPort">监听的端口</param> 132 133 public TCPServer(int listenPort) 134 135 : this(IPAddress.Any, listenPort, 1024) 136 137 { 138 139 } 140 141 142 143 /// <summary> 144 145 /// 同步TCP服务器 146 147 /// </summary> 148 149 /// <param name="localEP">监听的终结点</param> 150 151 public TCPServer(IPEndPoint localEP) 152 153 : this(localEP.Address, localEP.Port, 1024) 154 155 { 156 157 } 158 159 160 161 /// <summary> 162 163 /// 同步TCP服务器 164 165 /// </summary> 166 167 /// <param name="localIPAddress">监听的IP地址</param> 168 169 /// <param name="listenPort">监听的端口</param> 170 171 /// <param name="maxClient">最大客户端数量</param> 172 173 public TCPServer(IPAddress localIPAddress, int listenPort, int maxClient) 174 175 { 176 177 this.Address = localIPAddress; 178 179 this.Port = listenPort; 180 181 this.Encoding = Encoding.Default; 182 183 184 185 _maxClient = maxClient; 186 187 _clients = new List<TCPClientHandle>(); 188 189 _listener = new TcpListener(new IPEndPoint(this.Address, this.Port)); 190 191 } 192 193 194 195 #endregion 196 197 198 199 #region Method 200 201 /// <summary> 202 203 /// 启动服务器 204 205 /// </summary> 206 207 public void Start() 208 209 { 210 211 if (!IsRunning) 212 213 { 214 215 IsRunning = true; 216 217 _listener.Start(); 218 219 Thread thread = new Thread(Accept); 220 221 thread.Start(); 222 223 } 224 225 } 226 227 /// <summary> 228 229 /// 开始进行监听 230 231 /// </summary> 232 233 private void Accept() 234 235 { 236 237 TCPClientHandle handle; 238 239 while (IsRunning) 240 241 { 242 243 TcpClient client = _listener.AcceptTcpClient(); 244 245 if (_clientCount >= _maxClient) 246 247 { 248 249 //TODO 触发事件 250 251 } 252 253 else 254 255 { 256 257 handle = new TCPClientHandle(client); 258 259 _clientCount++; 260 261 _clients.Add(handle); 262 263 264 265 //TODO 创建一个处理客户端的线程并启动 266 267 //使用线程池来操作 268 269 new Thread(new ThreadStart(handle.RecevieData)).Start(); 270 271 } 272 273 } 274 275 276 277 } 278 279 /// <summary> 280 281 /// 停止服务器 282 283 /// </summary> 284 285 public void Stop() 286 287 { 288 289 if (IsRunning) 290 291 { 292 293 IsRunning = false; 294 295 _listener.Stop(); 296 297 //TODO 关闭对所有客户端的连接 298 299 } 300 301 } 302 303 /// <summary> 304 305 /// 发送函数 306 307 /// </summary> 308 309 public void Send(string msg, TcpClient client) 310 311 { 312 313 //TODO 314 315 } 316 317 318 319 #endregion 320 321 322 323 #region 事件 324 325 326 327 /// <summary> 328 329 /// 与客户端的连接已建立事件 330 331 /// </summary> 332 333 public event EventHandler<TCPEventArgs> ClientConnected; 334 335 /// <summary> 336 337 /// 与客户端的连接已断开事件 338 339 /// </summary> 340 341 public event EventHandler<TCPEventArgs> ClientDisconnected; 342 343 344 345 /// <summary> 346 347 /// 触发客户端连接事件 348 349 /// </summary> 350 351 /// <param name="state"></param> 352 353 private void RaiseClientConnected(TCPClientHandle handle) 354 355 { 356 357 if (ClientConnected != null) 358 359 { 360 361 ClientConnected(this, new TCPEventArgs(handle)); 362 363 } 364 365 } 366 367 /// <summary> 368 369 /// 触发客户端连接断开事件 370 371 /// </summary> 372 373 /// <param name="client"></param> 374 375 private void RaiseClientDisconnected(Socket client) 376 377 { 378 379 if (ClientDisconnected != null) 380 381 { 382 383 ClientDisconnected(this, new TCPEventArgs("连接断开")); 384 385 } 386 387 } 388 389 390 391 /// <summary> 392 393 /// 接收到数据事件 394 395 /// </summary> 396 397 public event EventHandler<TCPEventArgs> DataReceived; 398 399 400 401 private void RaiseDataReceived(TCPClientHandle handle) 402 403 { 404 405 if (DataReceived != null) 406 407 { 408 409 DataReceived(this, new TCPEventArgs(handle)); 410 411 } 412 413 } 414 415 416 417 /// <summary> 418 419 /// 数据发送事件 420 421 /// </summary> 422 423 public event EventHandler<TCPEventArgs> CompletedSend; 424 425 426 427 /// <summary> 428 429 /// 触发数据发送事件 430 431 /// </summary> 432 433 /// <param name="state"></param> 434 435 private void RaiseCompletedSend(TCPClientHandle handle) 436 437 { 438 439 if (CompletedSend != null) 440 441 { 442 443 CompletedSend(this, new TCPEventArgs(handle)); 444 445 } 446 447 } 448 449 450 451 452 453 /// <summary> 454 455 /// 网络错误事件 456 457 /// </summary> 458 459 public event EventHandler<TCPEventArgs> NetError; 460 461 /// <summary> 462 463 /// 触发网络错误事件 464 465 /// </summary> 466 467 /// <param name="state"></param> 468 469 private void RaiseNetError(TCPClientHandle handle) 470 471 { 472 473 if (NetError != null) 474 475 { 476 477 NetError(this, new TCPEventArgs(handle)); 478 479 } 480 481 } 482 483 484 485 /// <summary> 486 487 /// 异常事件 488 489 /// </summary> 490 491 public event EventHandler<TCPEventArgs> OtherException; 492 493 /// <summary> 494 495 /// 触发异常事件 496 497 /// </summary> 498 499 /// <param name="state"></param> 500 501 private void RaiseOtherException(TCPClientHandle handle, string descrip) 502 503 { 504 505 if (OtherException != null) 506 507 { 508 509 OtherException(this, new TCPEventArgs(descrip, handle)); 510 511 } 512 513 } 514 515 private void RaiseOtherException(TCPClientHandle handle) 516 517 { 518 519 RaiseOtherException(handle, ""); 520 521 } 522 523 524 525 #endregion 526 527 528 529 #region Close 530 531 532 533 /// <summary> 534 535 /// 关闭一个与客户端之间的会话 536 537 /// </summary> 538 539 /// <param name="handle">需要关闭的客户端会话对象</param> 540 541 public void Close(TCPClientHandle handle) 542 543 { 544 545 if (handle != null) 546 547 { 548 549 _clients.Remove(handle); 550 551 handle.Dispose(); 552 553 _clientCount--; 554 555 //TODO 触发关闭事件 556 557 558 559 } 560 561 } 562 563 /// <summary> 564 565 /// 关闭所有的客户端会话,与所有的客户端连接会断开 566 567 /// </summary> 568 569 public void CloseAllClient() 570 571 { 572 573 foreach (TCPClientHandle handle in _clients) 574 575 { 576 577 Close(handle); 578 579 } 580 581 _clientCount = 0; 582 583 _clients.Clear(); 584 585 } 586 587 #endregion 588 589 590 591 #region 释放 592 593 /// <summary> 594 595 /// Performs application-defined tasks associated with freeing, 596 597 /// releasing, or resetting unmanaged resources. 598 599 /// </summary> 600 601 public void Dispose() 602 603 { 604 605 Dispose(true); 606 607 GC.SuppressFinalize(this); 608 609 } 610 611 612 613 /// <summary> 614 615 /// Releases unmanaged and - optionally - managed resources 616 617 /// </summary> 618 619 /// <param name="disposing"><c>true</c> to release 620 621 /// both managed and unmanaged resources; <c>false</c> 622 623 /// to release only unmanaged resources.</param> 624 625 protected virtual void Dispose(bool disposing) 626 627 { 628 629 if (!this.disposed) 630 631 { 632 633 if (disposing) 634 635 { 636 637 try 638 639 { 640 641 Stop(); 642 643 if (_listener != null) 644 645 { 646 647 _listener = null; 648 649 } 650 651 } 652 653 catch (SocketException) 654 655 { 656 657 //TODO 异常 658 659 } 660 661 } 662 663 disposed = true; 664 665 } 666 667 } 668 669 #endregion 670 671 } 672 673 }
客户端处理封装类:
1 using System; 2 3 using System.Collections.Generic; 4 5 using System.Linq; 6 7 using System.Text; 8 9 using System.Net.Sockets; 10 11 using System.IO; 12 13 14 15 namespace NetFrame.Net.TCP.Listener.Synchronous 16 17 { 18 19 /// <summary> 20 21 /// TcpListener实现同步TCP服务器 的客户端连接处理类 22 23 /// </summary> 24 25 public class TCPClientHandle 26 27 { 28 29 private TcpClient _tcpclient; 30 31 32 33 private BinaryReader rs; 34 35 36 37 private BinaryWriter ws; 38 39 40 41 /// <summary> 42 43 /// 标识是否与客户端相连接 44 45 /// </summary> 46 47 private bool _is_connect; 48 49 public bool IsConnect 50 51 { 52 53 get { return _is_connect; } 54 55 set { _is_connect = value; } 56 57 } 58 59 60 61 /// <summary> 62 63 /// 数据接受缓冲区 64 65 /// </summary> 66 67 private byte[] _recvBuffer; 68 69 70 71 public TCPClientHandle(TcpClient client) 72 73 { 74 75 _tcpclient = client; 76 77 rs = new BinaryReader(client.GetStream()); 78 79 ws = new BinaryWriter(client.GetStream()); 80 81 // NetworkStream ns = tmpTcpClient.GetStream(); 82 83 // if(ns.CanRead&&ns.CanWrite) 84 85 _recvBuffer=new byte[client.ReceiveBufferSize]; 86 87 } 88 89 90 91 /// <summary> 92 93 /// 接受数据 94 95 /// </summary> 96 97 public void RecevieData() 98 99 { 100 101 int len = 0; 102 103 while (_is_connect) 104 105 { 106 107 try 108 109 { 110 111 len = rs.Read(_recvBuffer, 0, _recvBuffer.Length); 112 113 } 114 115 catch (Exception) 116 117 { 118 119 break; 120 121 } 122 123 if (len == 0) 124 125 { 126 127 //the client has disconnected from server 128 129 break; 130 131 } 132 133 //TODO 处理收到的数据 134 135 136 137 } 138 139 } 140 141 /// <summary> 142 143 /// 向客户端发送数据 144 145 /// </summary> 146 147 /// <param name="msg"></param> 148 149 public void SendData(string msg) 150 151 { 152 153 byte[] data = Encoding.Default.GetBytes(msg); 154 155 try 156 157 { 158 159 ws.Write(data, 0, data.Length); 160 161 ws.Flush(); 162 163 } 164 165 catch (Exception) 166 167 { 168 169 //TODO 处理异常 170 171 } 172 173 } 174 175 176 177 #region 事件 178 179 180 181 182 183 //TODO 消息发送事件 184 185 //TODO 数据收到事件 186 187 //TODO 异常处理事件 188 189 190 191 #endregion 192 193 194 195 #region 释放 196 197 /// <summary> 198 199 /// Performs application-defined tasks associated with freeing, 200 201 /// releasing, or resetting unmanaged resources. 202 203 /// </summary> 204 205 public void Dispose() 206 207 { 208 209 _is_connect = false; 210 211 if (_tcpclient != null) 212 213 { 214 215 _tcpclient.Close(); 216 217 _tcpclient = null; 218 219 } 220 221 GC.SuppressFinalize(this); 222 223 } 224 225 226 227 #endregion 228 229 } 230 231 }
Tcp服务器事件参数类:
1 using System; 2 3 using System.Collections.Generic; 4 5 using System.Linq; 6 7 using System.Text; 8 9 10 11 namespace NetFrame.Net.TCP.Listener.Synchronous 12 13 { 14 15 /// <summary> 16 17 /// 同步TcpListener TCP服务器事件类 18 19 /// </summary> 20 21 public class TCPEventArgs : EventArgs 22 23 { 24 25 /// <summary> 26 27 /// 提示信息 28 29 /// </summary> 30 31 public string _msg; 32 33 34 35 /// <summary> 36 37 /// 客户端状态封装类 38 39 /// </summary> 40 41 public TCPClientHandle _handle; 42 43 44 45 /// <summary> 46 47 /// 是否已经处理过了 48 49 /// </summary> 50 51 public bool IsHandled { get; set; } 52 53 54 55 public TCPEventArgs(string msg) 56 57 { 58 59 this._msg = msg; 60 61 IsHandled = false; 62 63 } 64 65 public TCPEventArgs(TCPClientHandle handle) 66 67 { 68 69 this._handle = handle; 70 71 IsHandled = false; 72 73 } 74 75 public TCPEventArgs(string msg, TCPClientHandle handle) 76 77 { 78 79 this._msg = msg; 80 81 this._handle = handle; 82 83 IsHandled = false; 84 85 } 86 87 } 88 89 }

浙公网安备 33010602011771号