请选择 进入手机版 | 继续访问电脑版

马上加入IBC程序猿 各种源码随意下,各种教程随便看! 注册 每日签到 加入编程讨论群

C#教程 ASP.NET教程 C#视频教程程序源码享受不尽 C#问题入口 ASP.NET问题入口

【C#问题提交】 社群合作 申请版主 程序开发 【远程协助】 每天乐一乐 每日签到 【承接毕业设计】 面试-葵花宝典下载

官方一群:

官方二群:

查看: 1623|回复: 2

TCP多线程服务器代码共享

[复制链接]
  • TA的每日心情
    开心
    6 天前
  • 签到天数: 1595 天

    [LV.Master]伴坛终老

    4251

    主题

    6174

    帖子

    10万

    积分

    管理员

    IBC编程社区-原道楠

    Rank: 9Rank: 9Rank: 9

    积分
    109992

    推广达人突出贡献优秀版主荣誉管理论坛元老

    发表于 2017-5-23 09:01:39 | 显示全部楼层 |阅读模式

    马上加入IBC,查看更多教程

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    [C#] 纯文本查看 复制代码
    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;
    }
    }


    代码转载博客园,未经本人测试。

    C#论坛 www.ibcibc.com IBC编程社区
    C#
    C#论坛
    IBC编程社区
  • TA的每日心情
    开心
    6 天前
  • 签到天数: 1595 天

    [LV.Master]伴坛终老

    4251

    主题

    6174

    帖子

    10万

    积分

    管理员

    IBC编程社区-原道楠

    Rank: 9Rank: 9Rank: 9

    积分
    109992

    推广达人突出贡献优秀版主荣誉管理论坛元老

     楼主| 发表于 2017-5-23 09:29:47 | 显示全部楼层
    balabval
    C#论坛 www.ibcibc.com IBC编程社区
    C#
    C#论坛
    IBC编程社区
  • TA的每日心情
    难过
    2017-1-3 09:54
  • 签到天数: 1 天

    [LV.1]初来乍到

    0

    主题

    3

    帖子

    40

    积分

    新手上路

    Rank: 1

    积分
    40
    发表于 2017-5-23 09:45:05 | 显示全部楼层
    虽然看不太懂,也要占个前排
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则