文章系列目录
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
本文介绍
在.Net中,System.Net.Sockets 命名空间为需要严密控制网络访问的开发人员提供了 Windows Sockets (Winsock) 接口的托管实现。System.Net 命名空间中的所有其他网络访问类都建立在该套接字Socket实现之上,如TCPClient、TCPListener 和 UDPClient 类封装有关创建到 Internet 的 TCP 和 UDP 连接的详细信息;NetworkStream类则提供用于网络访问的基础数据流等,常见的许多Internet服务都可以见到Socket的踪影,如Telnet、Http、Email、Echo等,这些服务尽管通讯协议Protocol的定义不同,但是其基础的传输都是采用的Socket。 其实,Socket可以象流Stream一样被视为一个数据通道,这个通道架设在应用程序端(客户端)和远程服务器端之间,而后,数据的读取(接收)和写入(发送)均针对这个通道来进行。 可见,在应用程序端或者服务器端创建了Socket对象之后,就可以使用Send/SentTo方法将数据发送到连接的Socket,或者使用Receive/ReceiveFrom方法接收来自连接Socket的数据; 针对Socket编程,.NET 框架的 Socket 类是 Winsock32 API 提供的套接字服务的托管代码版本。其中为实现网络编程提供了大量的方法,大多数情况下,Socket 类方法只是将数据封送到它们的本机 Win32 副本中并处理任何必要的安全检查。如果你熟悉Winsock API函数,那么用Socket类编写网络程序会非常容易,当然,如果你不曾接触过,也不会太困难,跟随下面的解说,你会发觉使用Socket类开发windows
网络应用程序原来有规可寻,它们在大多数情况下遵循大致相同的步骤。
本节介绍使用Socket来实现一个高性能的异步UDP服务器,实际上UDP是不分客户机和服务器的,但是我们有的时候和服务器通讯就是使用UDP来进行的。
Socket异步UDP服务器:
1 using System; 2 3 using System.Collections.Generic; 4 5 using System.Linq; 6 7 using System.Text; 8 9 using System.Net; 10 11 using System.Net.Sockets; 12 13 14 15 namespace NetFrame.Net.UDP.Sock.Asynchronous 16 17 { 18 19 /// <summary> 20 21 /// SOCKET实现异步UDP服务器 22 23 /// </summary> 24 25 public class AsyncSocketUDPServer 26 27 { 28 29 #region Fields 30 31 /// <summary> 32 33 /// 服务器程序允许的最大客户端连接数 34 35 /// </summary> 36 37 private int _maxClient; 38 39 40 41 /// <summary> 42 43 /// 当前的连接的客户端数 44 45 /// </summary> 46 47 //private int _clientCount; 48 49 50 51 /// <summary> 52 53 /// 服务器使用的同步socket 54 55 /// </summary> 56 57 private Socket _serverSock; 58 59 60 61 /// <summary> 62 63 /// 客户端会话列表 64 65 /// </summary> 66 67 //private List<AsyncUDPSocketState> _clients; 68 69 70 71 private bool disposed = false; 72 73 74 75 /// <summary> 76 77 /// 数据接受缓冲区 78 79 /// </summary> 80 81 private byte[] _recvBuffer; 82 83 84 85 #endregion 86 87 88 89 #region Properties 90 91 92 93 /// <summary> 94 95 /// 服务器是否正在运行 96 97 /// </summary> 98 99 public bool IsRunning { get; private set; } 100 101 /// <summary> 102 103 /// 监听的IP地址 104 105 /// </summary> 106 107 public IPAddress Address { get; private set; } 108 109 /// <summary> 110 111 /// 监听的端口 112 113 /// </summary> 114 115 public int Port { get; private set; } 116 117 /// <summary> 118 119 /// 通信使用的编码 120 121 /// </summary> 122 123 public Encoding Encoding { get; set; } 124 125 126 127 #endregion 128 129 130 131 #region 构造函数 132 133 134 135 /// <summary> 136 137 /// 异步Socket UDP服务器 138 139 /// </summary> 140 141 /// <param name="listenPort">监听的端口</param> 142 143 public AsyncSocketUDPServer(int listenPort) 144 145 : this(IPAddress.Any, listenPort,1024) 146 147 { 148 149 } 150 151 152 153 /// <summary> 154 155 /// 异步Socket UDP服务器 156 157 /// </summary> 158 159 /// <param name="localEP">监听的终结点</param> 160 161 public AsyncSocketUDPServer(IPEndPoint localEP) 162 163 : this(localEP.Address, localEP.Port,1024) 164 165 { 166 167 } 168 169 170 171 /// <summary> 172 173 /// 异步Socket UDP服务器 174 175 /// </summary> 176 177 /// <param name="localIPAddress">监听的IP地址</param> 178 179 /// <param name="listenPort">监听的端口</param> 180 181 /// <param name="maxClient">最大客户端数量</param> 182 183 public AsyncSocketUDPServer(IPAddress localIPAddress, int listenPort, int maxClient) 184 185 { 186 187 this.Address = localIPAddress; 188 189 this.Port = listenPort; 190 191 this.Encoding = Encoding.Default; 192 193 194 195 _maxClient = maxClient; 196 197 //_clients = new List<AsyncUDPSocketState>(); 198 199 _serverSock = new Socket(localIPAddress.AddressFamily, SocketType.Dgram, ProtocolType.Udp); 200 201 202 203 _recvBuffer=new byte[_serverSock.ReceiveBufferSize]; 204 205 } 206 207 208 209 #endregion 210 211 212 213 #region Method 214 215 /// <summary> 216 217 /// 启动服务器 218 219 /// </summary> 220 221 /// <returns>异步TCP服务器</returns> 222 223 public void Start() 224 225 { 226 227 if (!IsRunning) 228 229 { 230 231 IsRunning = true; 232 233 _serverSock.Bind(new IPEndPoint(this.Address, this.Port)); 234 235 //_serverSock.Connect(new IPEndPoint(IPAddress.Any, 0)); 236 237 238 239 AsyncSocketUDPState so = new AsyncSocketUDPState(); 240 241 so.workSocket = _serverSock; 242 243 244 245 _serverSock.BeginReceiveFrom(so.buffer, 0, so.buffer.Length, SocketFlags.None, 246 247 ref so.remote, new AsyncCallback(ReceiveDataAsync), null); 248 249 250 251 252 253 //EndPoint sender = new IPEndPoint(IPAddress.Any, 0); 254 255 256 257 //_serverSock.BeginReceiveFrom(_recvBuffer, 0, _recvBuffer.Length, SocketFlags.None, 258 259 // ref sender, new AsyncCallback(ReceiveDataAsync), sender); 260 261 262 263 //BeginReceive 和 BeginReceiveFrom的区别是什么 264 265 /*_serverSock.BeginReceive(_recvBuffer, 0, _recvBuffer.Length, SocketFlags.None, 266 267 new AsyncCallback(ReceiveDataAsync), null);*/ 268 269 } 270 271 } 272 273 274 275 /// <summary> 276 277 /// 停止服务器 278 279 /// </summary> 280 281 public void Stop() 282 283 { 284 285 if (IsRunning) 286 287 { 288 289 IsRunning = false; 290 291 _serverSock.Close(); 292 293 //TODO 关闭对所有客户端的连接 294 295 296 297 } 298 299 } 300 301 302 303 /// <summary> 304 305 /// 接收数据的方法 306 307 /// </summary> 308 309 /// <param name="ar"></param> 310 311 private void ReceiveDataAsync(IAsyncResult ar) 312 313 { 314 315 AsyncSocketUDPState so = ar.AsyncState as AsyncSocketUDPState; 316 317 //EndPoint sender = new IPEndPoint(IPAddress.Any, 0); 318 319 int len = -1; 320 321 try 322 323 { 324 325 len = _serverSock.EndReceiveFrom(ar, ref so.remote); 326 327 328 329 //len = _serverSock.EndReceiveFrom(ar, ref sender); 330 331 332 333 //EndReceiveFrom 和 EndReceive区别 334 335 //len = _serverSock.EndReceive(ar); 336 337 //TODO 处理数据 338 339 340 341 //触发数据收到事件 342 343 RaiseDataReceived(so); 344 345 } 346 347 catch (Exception) 348 349 { 350 351 //TODO 处理异常 352 353 RaiseOtherException(so); 354 355 } 356 357 finally 358 359 { 360 361 if (IsRunning && _serverSock != null) 362 363 _serverSock.BeginReceiveFrom(so.buffer, 0, so.buffer.Length, SocketFlags.None, 364 365 ref so.remote, new AsyncCallback(ReceiveDataAsync), so); 366 367 } 368 369 } 370 371 /// <summary> 372 373 /// 发送数据 374 375 /// </summary> 376 377 /// <param name="msg"></param> 378 379 /// <param name="remote"></param> 380 381 public void Send(string msg,EndPoint remote) 382 383 { 384 385 byte[] data = Encoding.Default.GetBytes(msg); 386 387 try 388 389 { 390 391 RaisePrepareSend(null); 392 393 _serverSock.BeginSendTo(data, 0, data.Length, SocketFlags.None, remote, new AsyncCallback(SendDataEnd), _serverSock); 394 395 } 396 397 catch (Exception) 398 399 { 400 401 //TODO 异常处理 402 403 RaiseOtherException(null); 404 405 } 406 407 } 408 409 410 411 private void SendDataEnd(IAsyncResult ar) 412 413 { 414 415 ((Socket)ar.AsyncState).EndSendTo(ar); 416 417 RaiseCompletedSend(null); 418 419 } 420 421 422 423 #endregion 424 425 426 427 #region 事件 428 429 /// <summary> 430 431 /// 接收到数据事件 432 433 /// </summary> 434 435 public event EventHandler<AsyncSocketUDPEventArgs> DataReceived; 436 437 438 439 private void RaiseDataReceived(AsyncSocketUDPState state) 440 441 { 442 443 if (DataReceived != null) 444 445 { 446 447 DataReceived(this, new AsyncSocketUDPEventArgs(state)); 448 449 } 450 451 } 452 453 454 455 /// <summary> 456 457 /// 发送数据前的事件 458 459 /// </summary> 460 461 public event EventHandler<AsyncSocketUDPEventArgs> PrepareSend; 462 463 464 465 /// <summary> 466 467 /// 触发发送数据前的事件 468 469 /// </summary> 470 471 /// <param name="state"></param> 472 473 private void RaisePrepareSend(AsyncSocketUDPState state) 474 475 { 476 477 if (PrepareSend != null) 478 479 { 480 481 PrepareSend(this, new AsyncSocketUDPEventArgs(state)); 482 483 } 484 485 } 486 487 488 489 /// <summary> 490 491 /// 数据发送完毕事件 492 493 /// </summary> 494 495 public event EventHandler<AsyncSocketUDPEventArgs> CompletedSend; 496 497 498 499 /// <summary> 500 501 /// 触发数据发送完毕的事件 502 503 /// </summary> 504 505 /// <param name="state"></param> 506 507 private void RaiseCompletedSend(AsyncSocketUDPState state) 508 509 { 510 511 if (CompletedSend != null) 512 513 { 514 515 CompletedSend(this, new AsyncSocketUDPEventArgs(state)); 516 517 } 518 519 } 520 521 522 523 /// <summary> 524 525 /// 网络错误事件 526 527 /// </summary> 528 529 public event EventHandler<AsyncSocketUDPEventArgs> NetError; 530 531 /// <summary> 532 533 /// 触发网络错误事件 534 535 /// </summary> 536 537 /// <param name="state"></param> 538 539 private void RaiseNetError(AsyncSocketUDPState state) 540 541 { 542 543 if (NetError != null) 544 545 { 546 547 NetError(this, new AsyncSocketUDPEventArgs(state)); 548 549 } 550 551 } 552 553 554 555 /// <summary> 556 557 /// 异常事件 558 559 /// </summary> 560 561 public event EventHandler<AsyncSocketUDPEventArgs> OtherException; 562 563 /// <summary> 564 565 /// 触发异常事件 566 567 /// </summary> 568 569 /// <param name="state"></param> 570 571 private void RaiseOtherException(AsyncSocketUDPState state, string descrip) 572 573 { 574 575 if (OtherException != null) 576 577 { 578 579 OtherException(this, new AsyncSocketUDPEventArgs(descrip, state)); 580 581 } 582 583 } 584 585 private void RaiseOtherException(AsyncSocketUDPState state) 586 587 { 588 589 RaiseOtherException(state, ""); 590 591 } 592 593 #endregion 594 595 596 597 #region Close 598 599 /// <summary> 600 601 /// 关闭一个与客户端之间的会话 602 603 /// </summary> 604 605 /// <param name="state">需要关闭的客户端会话对象</param> 606 607 public void Close(AsyncSocketUDPState state) 608 609 { 610 611 if (state != null) 612 613 { 614 615 //_clients.Remove(state); 616 617 //_clientCount--; 618 619 //TODO 触发关闭事件 620 621 } 622 623 } 624 625 /// <summary> 626 627 /// 关闭所有的客户端会话,与所有的客户端连接会断开 628 629 /// </summary> 630 631 public void CloseAllClient() 632 633 { 634 635 //foreach (AsyncUDPSocketState client in _clients) 636 637 //{ 638 639 // Close(client); 640 641 //} 642 643 //_clientCount = 0; 644 645 //_clients.Clear(); 646 647 } 648 649 650 651 #endregion 652 653 654 655 #region 释放 656 657 /// <summary> 658 659 /// Performs application-defined tasks associated with freeing, 660 661 /// releasing, or resetting unmanaged resources. 662 663 /// </summary> 664 665 public void Dispose() 666 667 { 668 669 Dispose(true); 670 671 GC.SuppressFinalize(this); 672 673 } 674 675 676 677 /// <summary> 678 679 /// Releases unmanaged and - optionally - managed resources 680 681 /// </summary> 682 683 /// <param name="disposing"><c>true</c> to release 684 685 /// both managed and unmanaged resources; <c>false</c> 686 687 /// to release only unmanaged resources.</param> 688 689 protected virtual void Dispose(bool disposing) 690 691 { 692 693 if (!this.disposed) 694 695 { 696 697 if (disposing) 698 699 { 700 701 try 702 703 { 704 705 Stop(); 706 707 if (_serverSock != null) 708 709 { 710 711 _serverSock = null; 712 713 } 714 715 } 716 717 catch (SocketException) 718 719 { 720 721 //TODO 722 723 RaiseOtherException(null); 724 725 } 726 727 } 728 729 disposed = true; 730 731 } 732 733 } 734 735 #endregion 736 737 } 738 739 }
会话封装类:
1 using System; 2 3 using System.Collections.Generic; 4 5 using System.Linq; 6 7 using System.Text; 8 9 using System.Net; 10 11 using System.Net.Sockets; 12 13 14 15 namespace NetFrame.Net.UDP.Sock.Asynchronous 16 17 { 18 19 public class AsyncSocketUDPState 20 21 { 22 23 // Client socket. 24 25 public Socket workSocket = null; 26 27 // Size of receive buffer. 28 29 public const int BufferSize = 1024; 30 31 // Receive buffer. 32 33 public byte[] buffer = new byte[BufferSize]; 34 35 // Received data string. 36 37 public StringBuilder sb = new StringBuilder(); 38 39 40 41 public EndPoint remote = new IPEndPoint(IPAddress.Any, 0); 42 43 } 44 45 }
Socket异步UDP服务器事件参数类:
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.UDP.Sock.Asynchronous 12 13 { 14 15 /// <summary> 16 17 /// SOCKET 异步UDP 事件类 18 19 /// </summary> 20 21 public class AsyncSocketUDPEventArgs : 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 AsyncSocketUDPState _state; 42 43 44 45 /// <summary> 46 47 /// 是否已经处理过了 48 49 /// </summary> 50 51 public bool IsHandled { get; set; } 52 53 54 55 public AsyncSocketUDPEventArgs(string msg) 56 57 { 58 59 this._msg = msg; 60 61 IsHandled = false; 62 63 } 64 65 public AsyncSocketUDPEventArgs(AsyncSocketUDPState state) 66 67 { 68 69 this._state = state; 70 71 IsHandled = false; 72 73 } 74 75 public AsyncSocketUDPEventArgs(string msg, AsyncSocketUDPState state) 76 77 { 78 79 this._msg = msg; 80 81 this._state = state; 82 83 IsHandled = false; 84 85 } 86 87 } 88 89 }

浙公网安备 33010602011771号