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

浙公网安备 33010602011771号