自定义SocketTcpServer,虽然现在有很多这样的组件,但是有时候还是需要把它集成在你的框架或者产品中,不需要特别强大的功能,根据需求定制。最基本的一个问题是判断数据包的结束,没有像supersocket那样默认以换行作为一个命令的结束,如果需要可以改善。

  1. public interface ISocketTcpServer
  2. {
  3. void Listen();
  4. void Stop();
  5. void SendData(byte[] data, Socket client);
  6.  
  7. event ReceiveDataHandler ReceivedDataEvent;
  8. event OnlineChangeHandler OnlineChangeEvent;
  9. event ErrorHandler ErrorEvent;
  10. }
  11.  
  12. public delegate void ReceiveDataHandler(SocketState state);
  13.  
  14. public delegate void OnlineChangeHandler(int onlines, EndPoint client);
  15.  
  16. public delegate void ErrorHandler(string error, EndPoint client);
  17.  
  18. public class SocketTcpServer : ISocketTcpServer
  19. {
  20. private readonly Socket _tcpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  21. public readonly EndPoint LocalPoint;
  22. public readonly List<SocketState> ClientList = new List<SocketState>();
  23. public bool IsListening;
  24.  
  25. public SocketTcpServer(IPEndPoint localPoint)
  26. {
  27. LocalPoint = localPoint;
  28. }
  29.  
  30. public void Listen()
  31. {
  32. _tcpSocket.Bind(LocalPoint);
  33. _tcpSocket.Listen();
  34. _tcpSocket.BeginAccept(AcceptClientCallBack, _tcpSocket);
  35. IsListening = true;
  36. }
  37.  
  38. public void Stop()
  39. {
  40. IsListening = false;
  41. foreach (var state in ClientList)
  42. {
  43. state.ClientSocket.Close();
  44. }
  45. ClientList.Clear();
  46. _tcpSocket.Close();
  47. OnlineChangeEvent?.Invoke(ClientList.Count, new IPEndPoint(IPAddress.Any, ));
  48. }
  49.  
  50. private void AcceptClientCallBack(IAsyncResult ar)
  51. {
  52. var server = ar.AsyncState as Socket;
  53. if (IsListening && server != null)
  54. {
  55. try
  56. {
  57. var client = server.EndAccept(ar);
  58. var clientState = new SocketState()
  59. {
  60. ClientSocket = client,
  61. RemotePoint = client.RemoteEndPoint,
  62. };
  63. var tem = ClientList.FirstOrDefault(x => x.RemotePoint.Equals(clientState.RemotePoint));
  64. if (tem != null)
  65. {
  66. tem.ClientSocket.Close();
  67. ClientList.Remove(tem);
  68. }
  69. ClientList.Add(clientState);
  70. BeginReveive(client);
  71. OnlineChangeEvent?.Invoke(ClientList.Count, client.RemoteEndPoint);
  72. }
  73. catch (Exception error)
  74. {
  75. ErrorEvent?.Invoke(error.Message, null);
  76. }
  77. finally
  78. {
  79. server.BeginAccept(AcceptClientCallBack, server);
  80. }
  81. }
  82. }
  83.  
  84. private void BeginReveive(Socket client)
  85. {
  86. if (client.Connected)
  87. {
  88. var state = new SocketState()
  89. {
  90. ClientSocket = client,
  91. RemotePoint = client.RemoteEndPoint,
  92. };
  93. client.BeginReceiveFrom(
  94. state.Buffer,
  95. ,
  96. state.Buffer.Length,
  97. SocketFlags.None,
  98. ref state.RemotePoint,
  99. ReceiveCallback,
  100. state);
  101. }
  102. }
  103.  
  104. private void ReceiveCallback(IAsyncResult ar)
  105. {
  106. var state = ar.AsyncState as SocketState;
  107. try
  108. {
  109. if (state != null && state.ClientSocket.Connected)
  110. {
  111. state.DataLen = state.ClientSocket.EndReceiveFrom(ar, ref state.RemotePoint);
  112. if (state.DataLen == )
  113. {
  114. state.ClientSocket.Close();
  115. var tem = ClientList.FirstOrDefault(x => x.RemotePoint.Equals(state.RemotePoint));
  116. ClientList.Remove(tem);
  117. OnlineChangeEvent?.Invoke(ClientList.Count, state.RemotePoint);
  118. }
  119. else
  120. {
  121. byte[] receivedData = new byte[state.DataLen];
  122. Array.Copy(state.Buffer, , receivedData, , state.DataLen);
  123. state.Buffer = receivedData;
  124. ReceivedDataEvent?.Invoke(state);
  125. }
  126. }
  127. }
  128. catch (Exception error)
  129. {
  130. ErrorEvent?.Invoke(error.Message, state.RemotePoint);
  131. state.ClientSocket.Close();
  132. var tem = ClientList.FirstOrDefault(x => x.RemotePoint.Equals(state.RemotePoint));
  133. ClientList.Remove(tem);
  134. OnlineChangeEvent?.Invoke(ClientList.Count, state.RemotePoint);
  135. }
  136. finally
  137. {
  138. if (state != null) BeginReveive(state.ClientSocket);
  139. }
  140. }
  141.  
  142. public void SendData(byte[] data, Socket client)
  143. {
  144. if (client.Connected)
  145. {
  146. var state = new SocketState()
  147. {
  148. ClientSocket = client,
  149. RemotePoint = client.RemoteEndPoint,
  150. Buffer = data,
  151. DataLen = data.Length,
  152. };
  153. client.BeginSendTo(data, , data.Length, SocketFlags.None, state.RemotePoint, SendCallback, state);
  154. }
  155. }
  156.  
  157. private void SendCallback(IAsyncResult ar)
  158. {
  159. var state = ar.AsyncState as SocketState;
  160. try
  161. {
  162. if (state != null && state.ClientSocket.Connected)
  163. {
  164. state.ClientSocket.EndSendTo(ar);
  165. }
  166. }
  167. catch (Exception error)
  168. {
  169. ErrorEvent?.Invoke(error.Message, state.RemotePoint);
  170. }
  171. }
  172.  
  173. public event ReceiveDataHandler ReceivedDataEvent;
  174.  
  175. public event OnlineChangeHandler OnlineChangeEvent;
  176.  
  177. public event ErrorHandler ErrorEvent;
  178. }
  179.  
  180. public class SocketState
  181. {
  182. public byte[] Buffer = new byte[*];
  183. public Socket ClientSocket;
  184. public int DataLen;
  185. public EndPoint RemotePoint;
  186. }

SocketTcpServer的更多相关文章

  1. C#网络编程系列(两)它Socket同步TCPserver

    声明原文 笔者:竹zz  本文地址http://blog.csdn.net/zhujunxxxxx/article/details/44258719 转载请注明出处 文章系列文件夹 C#网络编程系列文 ...

  2. Unity C# 自定义TCP传输协议以及封包拆包、解决粘包问题

    本文只是初步实现了一个简单的TCP自定协议,更为复杂的协议可以根据这种方式去扩展. TCP协议,通俗一点的讲,它是一种基于socket传输的由发送方和接收方事先协商好的一种消息包组成结构,主要由消息头 ...

  3. QT创建TCP Socket通信

    最近在学习QT,了解到QT可以进行SOCKET网络通信,进行学习,并建立一个简单的聊天DEMO.为了测试是否能与VS2012下的程序进行通信,在VS2012下建立一个客户端程序,进行通信测试,发现可以 ...

  4. Android之socket服务端

    import java.io.DataInputStream; import java.io.IOException; import java.io.PrintWriter; import java. ...

  5. 8.9.网络编程_Socket 远程调用机制

    1.网络编程 1.1.网络编程概述: 通过通信线路(有线或无线)可以把不同地理位置且相互独立的计算机连同其外部设备连接起来,组成计算机网络.在操作系统.网络管理软件及网络 通信协议的管理和协调下,可以 ...

  6. 1、Socket通信

    [TCP] 服务器端:无目标插座升级为有目标插座后,就可以通过有目标的插座收发数据 客户端: 实战:此案例有利于理解Socket的工作流程. 缺点:服务器只能接收1个客户端的连接,因为只写了一个Acc ...

随机推荐

  1. [SoapUI] 同一个Resource不同参数时,在两个step里默认打开总是同一个Resource

    当SoapUI里Projects 有两个相同的Resource,只是参数不同时,使用两个Resource创建的step默认打开的总是同一个Resource.我们应当修改method名字为不同,这是So ...

  2. 转!!log4j基础

    log4j组件介绍 Log4j主要有三个组件: Logger:负责供客户端代码调用,执行debug(Object msg).info(Object msg).warn(Object msg).erro ...

  3. 课时8—弹窗modal

    首先弹窗的实现效果如下: 主要实现的代码如下: CSS: .header,.footer,.wrap-page{ position:absolute; left:; right:; backgroun ...

  4. Echarts的基本用法

    首先需要到导入echatrs.js文件 <script src="dist/echarts.js"></script> 路径配置 require.confi ...

  5. 6/17 Sprint3

    首页改进:

  6. 运用js解决java selenium元素定位问题

    一.解决定位并操作uneditable元素 尝试了通过id,xpath等等定位元素后点击都提示Element is not clickable at point 再看了下可以click的元素发现上面有 ...

  7. Makefile三个有用变量$@,$^,$<

    $@:目标文件 $^:所有的依赖文件 $<:第一个依赖文件 使用上面三个变量就可以简化我们的Makefile文件: #简化后的Makefile main : main.o log.o test_ ...

  8. 转: JSTL SQL标签库 使用

    SQL标签库 JSTL提供了与数据库相关操作的标签,可以直接从页面上实现数据库操作的功能,在开发小型网站是可以很方便的实现数据的读取和操作.本章将详细介绍这些标签的功能和使用方法. SQL标签库从功能 ...

  9. 监听器初始化Job、JobTracker相应TaskTracker心跳、调度器分配task源码级分析

    JobTracker和TaskTracker分别启动之后(JobTracker启动流程源码级分析,TaskTracker启动过程源码级分析),taskTracker会通过心跳与JobTracker通信 ...

  10. wdcp 打开网页显示 Apache 2 Test Page powered by CentOS

    是因为更新过系统,安装并更新了系统自带的apache 执行这个命令即可 #ln -sf /www/wdlinux/init.d/httpd /etc/rc.d/init.d/httpd#reboot