C# TCP多线程服务器
封装好的类,直接上代码:
using System; using System.Collections.Generic; using System.Net; using System.Net.Sockets; using System.Threading; namespace YxSocketService { /// <summary> /// 定义Socket服务类 /// socketService = new YxSocketService(port); ///socketService.OnSocketReceive += SocketRecive; /// private void SocketRecive(string ipAndPort, byte[] data) /// { /// var s = System.Text.Encoding.Default.GetString(data); /// Console.WriteLine(ipAndPort + "=>" + s); /// } /// </summary> public class YxSocketService { public delegate void SocketReceiveHandler(string ipAndPort, byte[] datas); private Thread _threadWatch = null; // 负责监听客户端连接请求的 线程; private System.Net.Sockets.Socket _socketWatch = null; private Dictionary<string, System.Net.Sockets.Socket> _dict = new Dictionary<string, System.Net.Sockets.Socket>();//存放套接字 private Dictionary<string, Thread> _dictThread = new Dictionary<string, Thread>();//存放线程 public SocketReceiveHandler OnSocketReceive; public YxSocketService(int port) { // 创建负责监听的套接字,注意其中的参数; _socketWatch = new System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // 获得文本框中的IP对象; IPAddress address = IPAddress.Any; // .Parse("10.10.16.185"); // 创建包含ip和端口号的网络节点对象; IPEndPoint endPoint = new IPEndPoint(address, port); try { // 将负责监听的套接字绑定到唯一的ip和端口上; _socketWatch.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); _socketWatch.Bind(endPoint); } catch (SocketException ex) { YxLog.YxLog.Error(this.GetType(), ex); return; } // 设置监听队列的长度; _socketWatch.Listen(10000); // 创建负责监听的线程; _threadWatch = new Thread(WatchConnecting); _threadWatch.IsBackground = true; _threadWatch.Start(); YxLog.YxLog.Info("服务器启动监听成功=>" + endPoint); } public void Send(string ipAndPort, string msg) { try { System.Net.Sockets.Socket sokConnection = _dict[ipAndPort]; if (sokConnection == null) return; byte[] data = System.Text.Encoding.Default.GetBytes(msg); sokConnection.Send(data); } catch (Exception ex) { YxLog.YxLog.Error(ex); //throw; } } /// <summary> /// 监听客户端请求的方法; /// </summary> private void WatchConnecting() { while (true) // 持续不断的监听客户端的连接请求; { // 开始监听客户端连接请求,Accept方法会阻断当前的线程; System.Net.Sockets.Socket sokConnection = _socketWatch.Accept(); // 一旦监听到一个客户端的请求,就返回一个与该客户端通信的 套接字; YxLog.YxLog.Info("新客户端连接成功=>" + sokConnection.RemoteEndPoint); // 将与客户端连接的 套接字 对象添加到集合中; _dict.Add(sokConnection.RemoteEndPoint.ToString(), sokConnection); Thread thr = new Thread(RecMsg); thr.IsBackground = true; thr.Start(sokConnection); _dictThread.Add(sokConnection.RemoteEndPoint.ToString(), thr); // 将新建的线程 添加 到线程的集合中去。 } } void RecMsg(object sokConnectionparn) { System.Net.Sockets.Socket sokClient = sokConnectionparn as System.Net.Sockets.Socket; while (true) { // 定义一个缓存区; byte[] arrMsgRec = new byte[1024]; // 将接受到的数据存入到输入 arrMsgRec中; int length = -1; try { length = sokClient.Receive(arrMsgRec); // 接收数据,并返回数据的长度; if (length > 0) { byte[] data = new byte[length]; Array.Copy(arrMsgRec, data, length); //var s = YxFunctionHelper.ByteArrToHex(data); //如果是十六进制 var s = System.Text.Encoding.Default.GetString(data); //如果不是十六进制 YxLog.YxLog.Info(sokClient.RemoteEndPoint + " " + s); //主业务 //执行回调事件 if (OnSocketReceive != null) { OnSocketReceive(sokClient.RemoteEndPoint.ToString(), data); } } else { // 从 通信套接字 集合中删除被中断连接的通信套接字; _dict.Remove(sokClient.RemoteEndPoint.ToString()); // 从通信线程集合中删除被中断连接的通信线程对象; _dictThread.Remove(sokClient.RemoteEndPoint.ToString()); YxLog.YxLog.Info("" + sokClient.RemoteEndPoint + "断开连接"); //log.log("遇见异常"+se.Message); break; } } catch (SocketException se) { // 从 通信套接字 集合中删除被中断连接的通信套接字; _dict.Remove(sokClient.RemoteEndPoint.ToString()); // 从通信线程集合中删除被中断连接的通信线程对象; _dictThread.Remove(sokClient.RemoteEndPoint.ToString()); YxLog.YxLog.Error("" + sokClient.RemoteEndPoint + "断开,异常消息:" + se.Message); //log.log("遇见异常"+se.Message); break; } catch (Exception e) { // 从 通信套接字 集合中删除被中断连接的通信套接字; _dict.Remove(sokClient.RemoteEndPoint.ToString()); // 从通信线程集合中删除被中断连接的通信线程对象; _dictThread.Remove(sokClient.RemoteEndPoint.ToString()); YxLog.YxLog.Error(this.GetType(), e); // log.log("遇见异常" + e.Message); break; } } } } }
有些事情,没经历过不知道原理,没失败过不明白奥妙,没痛苦过不了解真谛。临渊羡鱼,不如退而结网!

浙公网安备 33010602011771号