c#tcp多线程服务器实例代码

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;

}

}