c#Socket Tcp服务端编程
创建一个socket服务类,绑定监听端口,
然后创建一个线程listen连接的客户端,
把监听到的客户端加入dictionary里面,以便于管理,
同时创建receive线程,循环接收数据加入list缓存区,解决粘包或者分包的情况,
关闭服务时,需要将连接上的socket逐个shutdown。
- /*
- *
- * 该类用于管理tcp连接通讯
- *
- */
- using System;
- using System.Collections.Generic;
- using System.Net.Sockets;
- using System.Threading;
- using System.Net;
- namespace Communication
- {
- /// <summary>
- /// 服务端
- /// </summary>
- public class MyTcpServer
- {
- private Socket ServerSocket = null;//服务端
- public Dictionary<string, MySession> dic_ClientSocket = new Dictionary<string, MySession>();//tcp客户端字典
- private Dictionary<string, Thread> dic_ClientThread = new Dictionary<string, Thread>();//线程字典,每新增一个连接就添加一条线程
- private bool Flag_Listen = true;//监听客户端连接的标志
- /// <summary>
- /// 启动服务
- /// </summary>
- /// <param name="port">端口号</param>
- public bool OpenServer(int port)
- {
- try
- {
- Flag_Listen = true;
- // 创建负责监听的套接字,注意其中的参数;
- ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
- // 创建包含ip和端口号的网络节点对象;
- IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, port);
- try
- {
- // 将负责监听的套接字绑定到唯一的ip和端口上;
- ServerSocket.Bind(endPoint);
- }
- catch
- {
- return false;
- }
- // 设置监听队列的长度;
- ServerSocket.Listen();
- // 创建负责监听的线程;
- Thread Thread_ServerListen = new Thread(ListenConnecting);
- Thread_ServerListen.IsBackground = true;
- Thread_ServerListen.Start();
- return true;
- }
- catch
- {
- return false;
- }
- }
- /// <summary>
- /// 关闭服务
- /// </summary>
- public void CloseServer()
- {
- lock (dic_ClientSocket)
- {
- foreach (var item in dic_ClientSocket)
- {
- item.Value.Close();//关闭每一个连接
- }
- dic_ClientSocket.Clear();//清除字典
- }
- lock (dic_ClientThread)
- {
- foreach (var item in dic_ClientThread)
- {
- item.Value.Abort();//停止线程
- }
- dic_ClientThread.Clear();
- }
- Flag_Listen = false;
- //ServerSocket.Shutdown(SocketShutdown.Both);//服务端不能主动关闭连接,需要把监听到的连接逐个关闭
- if (ServerSocket != null)
- ServerSocket.Close();
- }
- /// <summary>
- /// 监听客户端请求的方法;
- /// </summary>
- private void ListenConnecting()
- {
- while (Flag_Listen) // 持续不断的监听客户端的连接请求;
- {
- try
- {
- Socket sokConnection = ServerSocket.Accept(); // 一旦监听到一个客户端的请求,就返回一个与该客户端通信的 套接字;
- // 将与客户端连接的 套接字 对象添加到集合中;
- string str_EndPoint = sokConnection.RemoteEndPoint.ToString();
- MySession myTcpClient = new MySession() { TcpSocket = sokConnection };
- //创建线程接收数据
- Thread th_ReceiveData = new Thread(ReceiveData);
- th_ReceiveData.IsBackground = true;
- th_ReceiveData.Start(myTcpClient);
- //把线程及客户连接加入字典
- dic_ClientThread.Add(str_EndPoint, th_ReceiveData);
- dic_ClientSocket.Add(str_EndPoint, myTcpClient);
- }
- catch
- {
- }
- Thread.Sleep();
- }
- }
- /// <summary>
- /// 接收数据
- /// </summary>
- /// <param name="sokConnectionparn"></param>
- private void ReceiveData(object sokConnectionparn)
- {
- MySession tcpClient = sokConnectionparn as MySession;
- Socket socketClient = tcpClient.TcpSocket;
- bool Flag_Receive = true;
- while (Flag_Receive)
- {
- try
- {
- // 定义一个2M的缓存区;
- byte[] arrMsgRec = new byte[ * * ];
- // 将接受到的数据存入到输入 arrMsgRec中;
- int length = -;
- try
- {
- length = socketClient.Receive(arrMsgRec); // 接收数据,并返回数据的长度;
- }
- catch
- {
- Flag_Receive = false;
- // 从通信线程集合中删除被中断连接的通信线程对象;
- string keystr = socketClient.RemoteEndPoint.ToString();
- dic_ClientSocket.Remove(keystr);//删除客户端字典中该socket
- dic_ClientThread[keystr].Abort();//关闭线程
- dic_ClientThread.Remove(keystr);//删除字典中该线程
- tcpClient = null;
- socketClient = null;
- break;
- }
- byte[] buf = new byte[length];
- Array.Copy(arrMsgRec, buf, length);
- lock (tcpClient.m_Buffer)
- {
- tcpClient.AddQueue(buf);
- }
- }
- catch
- {
- }
- Thread.Sleep();
- }
- }
- /// <summary>
- /// 发送数据给指定的客户端
- /// </summary>
- /// <param name="_endPoint">客户端套接字</param>
- /// <param name="_buf">发送的数组</param>
- /// <returns></returns>
- public bool SendData(string _endPoint, byte[] _buf)
- {
- MySession myT = new MySession();
- if (dic_ClientSocket.TryGetValue(_endPoint, out myT))
- {
- myT.Send(_buf);
- return true;
- }
- else
- {
- return false;
- }
- }
- }
- /// <summary>
- /// 会话端
- /// </summary>
- public class MySession
- {
- public Socket TcpSocket;//socket对象
- public List<byte> m_Buffer = new List<byte>();//数据缓存区
- public MySession()
- {
- }
- /// <summary>
- /// 发送数据
- /// </summary>
- /// <param name="buf"></param>
- public void Send(byte[] buf)
- {
- if (buf != null)
- {
- TcpSocket.Send(buf);
- }
- }
- /// <summary>
- /// 获取连接的ip
- /// </summary>
- /// <returns></returns>
- public string GetIp()
- {
- IPEndPoint clientipe = (IPEndPoint)TcpSocket.RemoteEndPoint;
- string _ip = clientipe.Address.ToString();
- return _ip;
- }
- /// <summary>
- /// 关闭连接
- /// </summary>
- public void Close()
- {
- TcpSocket.Shutdown(SocketShutdown.Both);
- }
- /// <summary>
- /// 提取正确数据包
- /// </summary>
- public byte[] GetBuffer(int startIndex, int size)
- {
- byte[] buf = new byte[size];
- m_Buffer.CopyTo(startIndex, buf, , size);
- m_Buffer.RemoveRange(, startIndex + size);
- return buf;
- }
- /// <summary>
- /// 添加队列数据
- /// </summary>
- /// <param name="buffer"></param>
- public void AddQueue(byte[] buffer)
- {
- m_Buffer.AddRange(buffer);
- }
- /// <summary>
- /// 清除缓存
- /// </summary>
- public void ClearQueue()
- {
- m_Buffer.Clear();
- }
- }
- }
the end
c#Socket Tcp服务端编程的更多相关文章
- Java网络编程(TCP服务端)
/* * TCP服务端: * 1.创建服务端socket服务,并监听一个端口 * 2.服务端为了给客户端提供服务,获取客户端的内容,可以通过accept方法获取连接过来的客户端对象 * 3.可以通过获 ...
- python网络编程:socket、服务端、客户端
本文内容: socket介绍 TCP: 服务端 客户端 UDP: 服务端 客户端 首发时间:2018-02-08 01:14 修改: 2018-03-20 :重置了布局,增加了UDP 什么是socke ...
- tcp服务端socket
import socket if __name__ == '__main__': # 创建tcp服务端socket tcp_server_socket = socket.socket(socket.A ...
- python编程系列---tcp服务端的简单实现
流程如下: """tcp服务端创建流程1. 创建服务端的tcp socket : server_socket 用于监听客户端的请求2. 绑定端口3. server_soc ...
- python网络编程-TCP服务端的开发
#TCP服务端开发 2 #方法说明 3 """ 4 bind(host,port)表示绑定端口号,host是ip地址,ip地址一般不进 行绑定,表示本机的任何一个ip地址 ...
- 《Linux多线程服务端编程:使用muduo C++网络库》上市半年重印两次,总印数达到了9000册
<Linux多线程服务端编程:使用muduo C++网络库>这本书自今年一月上市以来,半年之内已经重印两次(加上首印,一共是三次印刷),总印数达到了9000册,这在技术书里已经算是相当不错 ...
- 基于Select模型的Windows TCP服务端和客户端程序示例
最近跟着刘远东老师的<C++百万并发网络通信引擎架构与实现(服务端.客户端.跨平台)>,Bilibili视频地址为C++百万并发网络通信引擎架构与实现(服务端.客户端.跨平台),重新复习下 ...
- C++封装的基于WinSock2的TCP服务端、客户端
无聊研究Winsock套接字编程,用原生的C语言接口写出来的代码看着难受,于是自己简单用C++封装一下,把思路过程理清,方便自己后续翻看和新手学习. 只写好了TCP通信服务端,有空把客户端流程也封装一 ...
- 利用select实现IO多路复用TCP服务端
一.相关函数 1. int select(int maxfdp, fd_set *readset, fd_set *writeset, fd_set *exceptset,struct timeva ...
随机推荐
- 【java】之位运算^,&,<<,>>,<<<,>>>总结
1.^(亦或运算) ,针对二进制,相同的为0,不同的为1 public static void main(String[] args) { System.out.println("2^3运算 ...
- 图片支持get请求访问
BufferedInputStream in = new BufferedInputStream(doc2.getContent());//读取文件到输入流 OutputStream out = re ...
- qnx spi 学习笔记
文档还在编辑中,目前排版很乱,边看边写..等写完了编辑 qnx spi 学习 --目前只是看了代码,学的不深入,有错误的地方请联系我 谢谢 spi init spi init应该是分为2条线,一条是 ...
- mysql常规巡检
mysql常规巡检 目录 一.巡检脚本 二.下载巡检脚本 三.脚本执行说明 1.inspection.conf 使用说明 2.inspection_mysql.sh 使用说明 3.mysqltun ...
- Python基础之变量
变量的作用 用来记录状态的变化 全局变量 全局变量一般使用大写字母来进行区分 顶头写 定义过之后在整个程序中都能使用, 如果需要在函数中使用并修改全局变量的值需要加上global关键字: 如果函数内部 ...
- 无外接键盘安装 raspberry pi 3B+ 安装系统
从官网介绍看,当前raspbian和以前大家的记录略有不同,老的博客资料基本都是介绍下载raspbian,但现在raspbian已经不再维护镜像, raspbian系统开始由官方 pi foundat ...
- 浅谈角色换装功能--Unity简单例子实现
在前置篇中,基本上梳理了一下换装功能背后涉及到的美术工作流.但程序员嘛,功能终归是要落到代码上的.本文中会结合Unity提供的API及之前提到的内容来实现一个简单的换装功能.效果如下: (图1:最终效 ...
- C语言的split功能
其它高级语言都有字符串的split功能,但C没有系统自带的,只能自己写一个了. void c_split(char *src, const char *separator, int maxlen, c ...
- Vue 使用axios获取数据
axios 的使用 1.安装 cnpm install axios --save 2.哪里用哪里引入axios <script> import Axios from 'axios' ...
- 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的中央仓库中没有这个资源,只能通过配 ...