创建一个socket服务类,绑定监听端口,

然后创建一个线程listen连接的客户端,

把监听到的客户端加入dictionary里面,以便于管理,

同时创建receive线程,循环接收数据加入list缓存区,解决粘包或者分包的情况,

关闭服务时,需要将连接上的socket逐个shutdown。

  1. /*
  2. *
  3. * 该类用于管理tcp连接通讯
  4. *
  5. */
  6.  
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Net.Sockets;
  10. using System.Threading;
  11. using System.Net;
  12.  
  13. namespace Communication
  14. {
  15. /// <summary>
  16. /// 服务端
  17. /// </summary>
  18. public class MyTcpServer
  19. {
  20.  
  21. private Socket ServerSocket = null;//服务端
  22. public Dictionary<string, MySession> dic_ClientSocket = new Dictionary<string, MySession>();//tcp客户端字典
  23. private Dictionary<string, Thread> dic_ClientThread = new Dictionary<string, Thread>();//线程字典,每新增一个连接就添加一条线程
  24. private bool Flag_Listen = true;//监听客户端连接的标志
  25.  
  26. /// <summary>
  27. /// 启动服务
  28. /// </summary>
  29. /// <param name="port">端口号</param>
  30. public bool OpenServer(int port)
  31. {
  32. try
  33. {
  34. Flag_Listen = true;
  35. // 创建负责监听的套接字,注意其中的参数;
  36. ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  37. // 创建包含ip和端口号的网络节点对象;
  38. IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, port);
  39. try
  40. {
  41. // 将负责监听的套接字绑定到唯一的ip和端口上;
  42. ServerSocket.Bind(endPoint);
  43. }
  44. catch
  45. {
  46. return false;
  47. }
  48. // 设置监听队列的长度;
  49. ServerSocket.Listen();
  50. // 创建负责监听的线程;
  51. Thread Thread_ServerListen = new Thread(ListenConnecting);
  52. Thread_ServerListen.IsBackground = true;
  53. Thread_ServerListen.Start();
  54.  
  55. return true;
  56. }
  57. catch
  58. {
  59. return false;
  60. }
  61. }
  62. /// <summary>
  63. /// 关闭服务
  64. /// </summary>
  65. public void CloseServer()
  66. {
  67. lock (dic_ClientSocket)
  68. {
  69. foreach (var item in dic_ClientSocket)
  70. {
  71. item.Value.Close();//关闭每一个连接
  72. }
  73. dic_ClientSocket.Clear();//清除字典
  74. }
  75. lock (dic_ClientThread)
  76. {
  77. foreach (var item in dic_ClientThread)
  78. {
  79. item.Value.Abort();//停止线程
  80. }
  81. dic_ClientThread.Clear();
  82. }
  83. Flag_Listen = false;
  84. //ServerSocket.Shutdown(SocketShutdown.Both);//服务端不能主动关闭连接,需要把监听到的连接逐个关闭
  85. if (ServerSocket != null)
  86. ServerSocket.Close();
  87.  
  88. }
  89. /// <summary>
  90. /// 监听客户端请求的方法;
  91. /// </summary>
  92. private void ListenConnecting()
  93. {
  94. while (Flag_Listen) // 持续不断的监听客户端的连接请求;
  95. {
  96. try
  97. {
  98. Socket sokConnection = ServerSocket.Accept(); // 一旦监听到一个客户端的请求,就返回一个与该客户端通信的 套接字;
  99. // 将与客户端连接的 套接字 对象添加到集合中;
  100. string str_EndPoint = sokConnection.RemoteEndPoint.ToString();
  101. MySession myTcpClient = new MySession() { TcpSocket = sokConnection };
  102. //创建线程接收数据
  103. Thread th_ReceiveData = new Thread(ReceiveData);
  104. th_ReceiveData.IsBackground = true;
  105. th_ReceiveData.Start(myTcpClient);
  106. //把线程及客户连接加入字典
  107. dic_ClientThread.Add(str_EndPoint, th_ReceiveData);
  108. dic_ClientSocket.Add(str_EndPoint, myTcpClient);
  109. }
  110. catch
  111. {
  112.  
  113. }
  114. Thread.Sleep();
  115. }
  116. }
  117. /// <summary>
  118. /// 接收数据
  119. /// </summary>
  120. /// <param name="sokConnectionparn"></param>
  121. private void ReceiveData(object sokConnectionparn)
  122. {
  123. MySession tcpClient = sokConnectionparn as MySession;
  124. Socket socketClient = tcpClient.TcpSocket;
  125. bool Flag_Receive = true;
  126.  
  127. while (Flag_Receive)
  128. {
  129. try
  130. {
  131. // 定义一个2M的缓存区;
  132. byte[] arrMsgRec = new byte[ * * ];
  133. // 将接受到的数据存入到输入 arrMsgRec中;
  134. int length = -;
  135. try
  136. {
  137. length = socketClient.Receive(arrMsgRec); // 接收数据,并返回数据的长度;
  138. }
  139. catch
  140. {
  141. Flag_Receive = false;
  142. // 从通信线程集合中删除被中断连接的通信线程对象;
  143. string keystr = socketClient.RemoteEndPoint.ToString();
  144. dic_ClientSocket.Remove(keystr);//删除客户端字典中该socket
  145. dic_ClientThread[keystr].Abort();//关闭线程
  146. dic_ClientThread.Remove(keystr);//删除字典中该线程
  147.  
  148. tcpClient = null;
  149. socketClient = null;
  150. break;
  151. }
  152. byte[] buf = new byte[length];
  153. Array.Copy(arrMsgRec, buf, length);
  154. lock (tcpClient.m_Buffer)
  155. {
  156. tcpClient.AddQueue(buf);
  157. }
  158. }
  159. catch
  160. {
  161.  
  162. }
  163. Thread.Sleep();
  164. }
  165. }
  166. /// <summary>
  167. /// 发送数据给指定的客户端
  168. /// </summary>
  169. /// <param name="_endPoint">客户端套接字</param>
  170. /// <param name="_buf">发送的数组</param>
  171. /// <returns></returns>
  172. public bool SendData(string _endPoint, byte[] _buf)
  173. {
  174. MySession myT = new MySession();
  175. if (dic_ClientSocket.TryGetValue(_endPoint, out myT))
  176. {
  177. myT.Send(_buf);
  178. return true;
  179. }
  180. else
  181. {
  182. return false;
  183. }
  184. }
  185. }
  186.  
  187. /// <summary>
  188. /// 会话端
  189. /// </summary>
  190. public class MySession
  191. {
  192. public Socket TcpSocket;//socket对象
  193. public List<byte> m_Buffer = new List<byte>();//数据缓存区
  194.  
  195. public MySession()
  196. {
  197.  
  198. }
  199.  
  200. /// <summary>
  201. /// 发送数据
  202. /// </summary>
  203. /// <param name="buf"></param>
  204. public void Send(byte[] buf)
  205. {
  206. if (buf != null)
  207. {
  208. TcpSocket.Send(buf);
  209. }
  210. }
  211. /// <summary>
  212. /// 获取连接的ip
  213. /// </summary>
  214. /// <returns></returns>
  215. public string GetIp()
  216. {
  217. IPEndPoint clientipe = (IPEndPoint)TcpSocket.RemoteEndPoint;
  218. string _ip = clientipe.Address.ToString();
  219. return _ip;
  220. }
  221. /// <summary>
  222. /// 关闭连接
  223. /// </summary>
  224. public void Close()
  225. {
  226. TcpSocket.Shutdown(SocketShutdown.Both);
  227. }
  228. /// <summary>
  229. /// 提取正确数据包
  230. /// </summary>
  231. public byte[] GetBuffer(int startIndex, int size)
  232. {
  233. byte[] buf = new byte[size];
  234. m_Buffer.CopyTo(startIndex, buf, , size);
  235. m_Buffer.RemoveRange(, startIndex + size);
  236. return buf;
  237. }
  238.  
  239. /// <summary>
  240. /// 添加队列数据
  241. /// </summary>
  242. /// <param name="buffer"></param>
  243. public void AddQueue(byte[] buffer)
  244. {
  245. m_Buffer.AddRange(buffer);
  246. }
  247. /// <summary>
  248. /// 清除缓存
  249. /// </summary>
  250. public void ClearQueue()
  251. {
  252. m_Buffer.Clear();
  253. }
  254. }
  255. }

the end

c#Socket Tcp服务端编程的更多相关文章

  1. Java网络编程(TCP服务端)

    /* * TCP服务端: * 1.创建服务端socket服务,并监听一个端口 * 2.服务端为了给客户端提供服务,获取客户端的内容,可以通过accept方法获取连接过来的客户端对象 * 3.可以通过获 ...

  2. python网络编程:socket、服务端、客户端

    本文内容: socket介绍 TCP: 服务端 客户端 UDP: 服务端 客户端 首发时间:2018-02-08 01:14 修改: 2018-03-20 :重置了布局,增加了UDP 什么是socke ...

  3. tcp服务端socket

    import socket if __name__ == '__main__': # 创建tcp服务端socket tcp_server_socket = socket.socket(socket.A ...

  4. python编程系列---tcp服务端的简单实现

    流程如下: """tcp服务端创建流程1. 创建服务端的tcp socket : server_socket 用于监听客户端的请求2. 绑定端口3. server_soc ...

  5. python网络编程-TCP服务端的开发

    #TCP服务端开发 2 #方法说明 3 """ 4 bind(host,port)表示绑定端口号,host是ip地址,ip地址一般不进 行绑定,表示本机的任何一个ip地址 ...

  6. 《Linux多线程服务端编程:使用muduo C++网络库》上市半年重印两次,总印数达到了9000册

    <Linux多线程服务端编程:使用muduo C++网络库>这本书自今年一月上市以来,半年之内已经重印两次(加上首印,一共是三次印刷),总印数达到了9000册,这在技术书里已经算是相当不错 ...

  7. 基于Select模型的Windows TCP服务端和客户端程序示例

    最近跟着刘远东老师的<C++百万并发网络通信引擎架构与实现(服务端.客户端.跨平台)>,Bilibili视频地址为C++百万并发网络通信引擎架构与实现(服务端.客户端.跨平台),重新复习下 ...

  8. C++封装的基于WinSock2的TCP服务端、客户端

    无聊研究Winsock套接字编程,用原生的C语言接口写出来的代码看着难受,于是自己简单用C++封装一下,把思路过程理清,方便自己后续翻看和新手学习. 只写好了TCP通信服务端,有空把客户端流程也封装一 ...

  9. 利用select实现IO多路复用TCP服务端

    一.相关函数 1.  int select(int maxfdp, fd_set *readset, fd_set *writeset, fd_set *exceptset,struct timeva ...

随机推荐

  1. 【java】之位运算^,&,<<,>>,<<<,>>>总结

    1.^(亦或运算) ,针对二进制,相同的为0,不同的为1 public static void main(String[] args) { System.out.println("2^3运算 ...

  2. 图片支持get请求访问

    BufferedInputStream in = new BufferedInputStream(doc2.getContent());//读取文件到输入流 OutputStream out = re ...

  3. qnx spi 学习笔记

    文档还在编辑中,目前排版很乱,边看边写..等写完了编辑 qnx spi 学习  --目前只是看了代码,学的不深入,有错误的地方请联系我 谢谢 spi init spi init应该是分为2条线,一条是 ...

  4. mysql常规巡检

    mysql常规巡检   目录 一.巡检脚本 二.下载巡检脚本 三.脚本执行说明 1.inspection.conf 使用说明 2.inspection_mysql.sh 使用说明 3.mysqltun ...

  5. Python基础之变量

    变量的作用 用来记录状态的变化 全局变量 全局变量一般使用大写字母来进行区分 顶头写 定义过之后在整个程序中都能使用, 如果需要在函数中使用并修改全局变量的值需要加上global关键字: 如果函数内部 ...

  6. 无外接键盘安装 raspberry pi 3B+ 安装系统

    从官网介绍看,当前raspbian和以前大家的记录略有不同,老的博客资料基本都是介绍下载raspbian,但现在raspbian已经不再维护镜像, raspbian系统开始由官方 pi foundat ...

  7. 浅谈角色换装功能--Unity简单例子实现

    在前置篇中,基本上梳理了一下换装功能背后涉及到的美术工作流.但程序员嘛,功能终归是要落到代码上的.本文中会结合Unity提供的API及之前提到的内容来实现一个简单的换装功能.效果如下: (图1:最终效 ...

  8. C语言的split功能

    其它高级语言都有字符串的split功能,但C没有系统自带的,只能自己写一个了. void c_split(char *src, const char *separator, int maxlen, c ...

  9. Vue 使用axios获取数据

    axios  的使用 1.安装  cnpm  install  axios --save 2.哪里用哪里引入axios <script> import Axios from 'axios' ...

  10. Maven 下添加oracle11g的包 报Missing artifact com.oracle:ojdbc6:jar:11.2.0.1.0

    Missing artifact com.oracle:ojdbc6:jar:11.2.0.1.0 原因:Oracle 的ojdbc.jar是收费的,所以maven的中央仓库中没有这个资源,只能通过配 ...