using System;
using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows.Forms;using System.Net;
using System.Net.Sockets;using System.Threading;using System.Diagnostics;using System.Net.NetworkInformation;namespace 黄炎培_服务器
{ public partial class Form1 : Form { public Form1() { InitializeComponent(); }/// <summary>
/// 服务器倾听客户端连接线程 /// </summary> Thread threadWatchs = null;/// <summary>
/// 服务器套接字 /// </summary> Socket socketServer = null;/// <summary>
/// 服务器监控客户端连接情况的线程 /// </summary> Thread MonitoThread = null;/// <summary>
/// 客户端ip与套接字的集合 /// </summary> Dictionary<string, Socket> dictSocket = new Dictionary<string, Socket>();/// <summary>
/// 客户端ip与线程的集合 /// </summary> Dictionary<string, Thread> dictThread = new Dictionary<string, Thread>();/// <summary>
/// 客户端连接线程的数量 /// </summary> long numThreadVal = 0;/// <summary>
/// 服务器ip /// </summary> string strServerIP = "192.168.4.3";/// <summary>
/// 服务器端口 /// </summary> int serverPort = 8080;/// <summary>
/// 缓存数据长度 /// </summary> int receiveDataValLengt = 1024;//缓存区长度/// <summary>
/// 用于Ping客户端 /// </summary> Ping monitoPing = new Ping();/// <summary>
/// 异常断开的客户端 /// </summary> Dictionary<string, string> dictBodClient = new Dictionary<string, string>();/// <summary>
/// 指示释放释放线程 /// </summary> bool isClearThread = false;ulong numDataFlow;
private void Form1_Load(object sender, EventArgs e)
{ //开启服务器 openServer(strServerIP, serverPort); //开启服务器监控线程 MonitoThread = new Thread(monitoThreadsDynamic); //后台线程 MonitoThread.IsBackground = true; //启动线程 MonitoThread.Start(); }/// <summary>
/// 开始实时监控客户端的连接情况 /// </summary> void monitoThreadsDynamic() { delegateShowMseeage("开始实时监控客户端连接情况"); while (true) { Thread.Sleep(3000); try { foreach (var vv in dictSocket) { PingReply reply = monitoPing.Send(vv.Key.Split(':')[0],1000); //如果Ping通 if (reply.Status == IPStatus.Success) { //表示客户端连接正常 delegateShowMseeage("客户端" + vv.Key + "连接正常"); } else { delegateShowMseeage("客户端" + vv.Key + "连接异常"); //添加异常客户端连接到集合dictBodClient dictBodClient.Add(vv.Key, "old"); } }//释放异常连接的线程
foreach (var vvv in dictThread) { isClearThread = false; foreach (var vvvv in dictBodClient) { if (vvv.Key == vvvv.Key) { isClearThread = true; break; } } if (isClearThread) { vvv.Value.Abort(); delegateShowMseeage("客户端" + vvv.Key + "占用的线程已释放"); } }//从集合合中移除异常连接的客户端
foreach (var vvv in dictBodClient) { //从集合中移除客户端套接字 dictSocket.Remove(vvv.Key); //从集合中移除客户端线程 dictThread.Remove(vvv.Key); //从列表中移除客户端套接字的远程终结点 deleteClientSocket(vvv.Key); //跨线程显示提示数据 delegateShowMseeage("客户端" + vvv.Key + "断开连接"); } } catch (Exception se) { //MessageBox.Show(se.Message); delegateShowMseeage(se.Message); }dictBodClient.Clear();
//获得当前程序运行的线程总数量 numThreadVal = Process.GetCurrentProcess().Threads.Count; delegateShowMseeage("当前的线程总数量为:" + numThreadVal); //获得客户端连接所占用的线程数量 numThreadVal = dictThread.LongCount(); //跨线程显示消息 delegateShowMseeage("其中客户端连接的线程数量为:" + numThreadVal); } }/// <summary>
/// 开启服务器 /// </summary> /// <param name="serverIP"></param> /// <param name="serverPort"></param> void openServer(string serverIP, int serverPort) { //实例化服务器套接字 socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //配置网络端点 IPEndPoint ipAndPort = new IPEndPoint(IPAddress.Parse(serverIP), serverPort); try { //设置服务器套接字的连接参数 socketServer.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); //将网络端点绑定到服务器套接字 socketServer.Bind(ipAndPort); } catch (SocketException se) { MessageBox.Show("异常:" + se.Message); return; } //服务器开始倾听,指定最多客户端数量为10000 socketServer.Listen(10000); //实例化服务器倾听客户端连接的线程 threadWatchs = new Thread(WatchClientConnecting); //后台运行线程 threadWatchs.IsBackground = true; //启动线程 threadWatchs.Start(); //显示提示消息 showMesssge("服务器启动成功"); }/// <summary>
/// 开始倾听客户端 /// </summary> void WatchClientConnecting() { //跨线程显示提示消息 delegateShowMseeage("服务器开始倾听客户端连接"); while (true) { //倾听新的客户端连接请求 Socket newClientConnecting = socketServer.Accept(); //添加客户端套接字的远程终结点到列表 addClientSocket(newClientConnecting.RemoteEndPoint.ToString()); //新建一条新的客户端线程 Thread newClinetThread = new Thread(receiveData); //后台运行客户端 newClinetThread.IsBackground = true; //启动线程,并将 新客户端的套接字 绑定到线程执行的方法 newClinetThread.Start(newClientConnecting); //添加客户端套接字到集合 dictSocket.Add(newClientConnecting.RemoteEndPoint.ToString(), newClientConnecting); //添加客户端接受数据的线程到集合 dictThread.Add(newClientConnecting.RemoteEndPoint.ToString(), newClinetThread); //跨线程显示提示信息 delegateShowMseeage("新客户端:" + newClientConnecting.RemoteEndPoint.ToString()); } }/// <summary>
/// 接受数据 /// </summary> /// <param name="socketConnecting"></param> void receiveData(object socketConnecting) { //获取该线程绑定的客户端套接字 Socket socketClient = socketConnecting as Socket; while (true) { //新建一个缓存区 byte[] receiveDataVal = new byte[receiveDataValLengt]; //数据长度 int receiveDataLength = -1; try { //接受数据填入缓存区并获得数据长度 receiveDataLength = socketClient.Receive(receiveDataVal); //接受到数据 if (receiveDataLength > 0) { //跨线程显示接受到的数据 delegateShowReceiveData(socketClient, receiveDataVal, receiveDataLength); //综合处理接受到的数据 receiveDataIntegratedProcessing(receiveDataVal, receiveDataLength); numDataFlow += (uint)receiveDataLength; showDataFlow(); } else { //从集合中移除客户端套接字 dictSocket.Remove(socketClient.RemoteEndPoint.ToString()); //从集合中移除客户端线程 dictThread.Remove(socketClient.RemoteEndPoint.ToString()); //从列表中移除客户端套接字的远程终结点 deleteClientSocket(socketClient.RemoteEndPoint.ToString()); //跨线程显示提示数据 delegateShowMseeage("客户端" + socketClient.RemoteEndPoint.ToString() + "断开连接"); //释放该线程 return; } } catch { //从集合中移除客户端套接字 dictSocket.Remove(socketClient.RemoteEndPoint.ToString()); //从集合中移除客户端线程 dictThread.Remove(socketClient.RemoteEndPoint.ToString()); //从列表中移除客户端套接字的远程终结点 deleteClientSocket(socketClient.RemoteEndPoint.ToString()); //跨线程显示提示数据 delegateShowMseeage("异常:" + "客户端" + socketClient.RemoteEndPoint.ToString() + "断开连接"); //释放该线程 return; } } }/// <summary>
/// 综合处理接受到的数据 /// </summary> /// <param name="datas"></param> /// <param name="length"></param> void receiveDataIntegratedProcessing(byte[] datas, int length) { //if (length == 5) //{ // if (datas[0] == 0x11 && datas[4] == 0x11) // { // foreach (var clients in dictSocket) // { // newOneThreadSendDataToClient(clients.Value, datas, length); // } // } // else if (datas[0] == 0x12 && datas[4] == 0x12) // { // foreach (var clients in dictSocket) // { // newOneThreadSendDataToClient(clients.Value, datas, length); // } // } //} //******************************************************************* //将接受的数据发送给所有客户端 //******************************************************************* //遍历客户端套接字的集合 foreach (var clients in dictSocket) { //新建一条线程发送数据到客户端 newOneThreadSendDataToClient(clients.Value, datas, length); } }void newOneThreadSendDataToClient(Socket clientSocket, byte[] datas, int length)
{ //跨线程显示提示消息 delegateShowMseeage("新建一条线程准备开始发送数据"); //新建发送数据的参数模型 dataSendArgsMode sendDataArgs = new dataSendArgsMode(); //将客户端套接字绑定到模型 sendDataArgs.sockets = clientSocket; //将数据绑定到模型 sendDataArgs.datas = datas; //将数据长度绑定到模型 sendDataArgs.length = length; //新建发送数据到客户端的线程 Thread threadSendDataToClient = new Thread(sendDataToClient); //后台运行线程 threadSendDataToClient.IsBackground = true; //启动线程,并将 发送数据的参数模型 绑定到线程执行的方法 threadSendDataToClient.Start(sendDataArgs);}
/// <summary>
/// 发送数据到客户端 /// </summary> /// <param name="obj"></param> void sendDataToClient(object obj) { //获取用于发送数据的参数模型 dataSendArgsMode args = obj as dataSendArgsMode;try
{ //从数据参数模型中提取数据发送到模型中的客户端 args.sockets.Send(args.datas, 0, args.length, SocketFlags.None); //跨线程显示提示消息 delegateShowMseeage("数据:" + getStringFormByte(args.datas, args.length) + "发送到了客户端:" + args.sockets.RemoteEndPoint.ToString()); delegateShowMseeage("数据发送完毕,关闭线程"); //释放该线程 numDataFlow += (uint)args.length; showDataFlow(); return; } catch { //从集合中移除客户端套接字 dictSocket.Remove(args.sockets.RemoteEndPoint.ToString()); //从集合中移除客户端线程 dictThread.Remove(args.sockets.RemoteEndPoint.ToString()); //从列表中移除客户端套接字的远程终结点 deleteClientSocket(args.sockets.RemoteEndPoint.ToString()); //跨线程显示提示消息 delegateShowMseeage("异常:" + "客户端" + args.sockets.RemoteEndPoint.ToString() + "断开连接" + ",关闭该线程"); //释放该线程 return; }}
/// <summary>
/// 从列表中删除客户端 /// </summary> /// <param name="socket"></param> void deleteClientSocket(string strClientSocket) { //封装一个方法进行委托 Action<string> actionDelegate = (x) => { //从列表中移除指定客户端套接字的远程终结点 lbOnlineClient.Items.Remove(x.ToString()); }; //将参数委托到指定方法执行 txtMessage.Invoke(actionDelegate, strClientSocket); }/// <summary>
/// 添加客户端到列表 /// </summary> /// <param name="clientSocket"></param> void addClientSocket(string strClientSocket) { //封装一个方法进行委托 Action<string> actionDelegate = (x) => { //向列表中添加指定客户端套接字的远程终结点 lbOnlineClient.Items.Add(x.ToString()); }; //将参数委托到指定方法执行 txtMessage.Invoke(actionDelegate, strClientSocket); }/// <summary>
/// 跨线程显示接受到的数据 /// </summary> /// <param name="socket"></param> /// <param name="datas"></param> /// <param name="length"></param> void delegateShowReceiveData(Socket socket, Byte[] datas, int length) { //封装一个方法进行委托 Action<string> actionDelegate = (x) => { //向文本框追加文本 txtMessage.AppendText(System.DateTime.Now.ToString()+ " -> "+ x.ToString() + "\r\n"); txtMessage.ScrollToCaret(); }; //将参数委托到指定方法执行 txtMessage.Invoke(actionDelegate, "收到来自 " + socket.RemoteEndPoint.ToString() + " 的数据:" + getStringFormByte(datas, length)); } /// <summary> /// 跨线程显示数据 /// </summary> /// <param name="message"></param> void delegateShowMseeage(string message) { //封装一个方法进行委托 Action<string> actionDelegate = (x) => { if (txtMessage.Text.Length > 2000000) txtMessage.Text = string.Empty; //向文本框追加文本 txtMessage.AppendText(System.DateTime.Now.ToString()+" -> " + x.ToString() + "\r\n"); txtMessage.ScrollToCaret(); }; //将参数委托到指定方法执行 txtMessage.Invoke(actionDelegate, message);}
/// <summary>
/// 显示数据流量 /// </summary> void showDataFlow() { //封装一个方法进行委托 Action<string> actionDelegateShowFlow = (x) => { lblDataFlow.Text = x.ToString(); }; //将参数委托到指定方法执行 lblDataFlow.Invoke(actionDelegateShowFlow, numDataFlow.ToString()); }/// <summary>
/// 显示数据 /// </summary> /// <param name="message"></param> void showMesssge(string message) { //向文本框追加文本 txtMessage.AppendText(System.DateTime.Now.ToString() + " -> " + message + "\r\n"); txtMessage.ScrollToCaret(); } /// <summary> /// 16进制的字符串形式 /// </summary> /// <param name="data"></param> /// <param name="length"></param> /// <returns></returns> string getStringFormByte(byte[] data, int length) { string str = ""; for (int i = 0; i < length; i++) { str += data[i].ToString("X").PadLeft(2, '0') + ' '; } return str; } }/// <summary>
/// 发送数据的参数 /// </summary> class dataSendArgsMode { /// <summary> /// 套接字 /// </summary> public Socket sockets;/// <summary>
/// 数据 /// </summary> public byte[] datas;/// <summary>
/// 长度 /// </summary> public int length; }}