• 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() + " ");
    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() + " ");
    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 + " ");
    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;
    }
    }

  • 相关阅读:
    转 Android的消息处理机制
    转 Android的消息处理机制(图+源码分析)——Looper,Handler,Message
    Android如何获取开机启动项列表
    在Android里完美实现基站和WIFI定位
    managedQuery和query的区别,
    Android WIFI 操作
    转:Android 获取Root权限
    CocoaPods: 制作cocoapods国内镜像
    CentosOS 7: 创建Nginx+Https网站
    Mac: 通过蓝牙用安卓手机向Mac发送文件
  • 原文地址:https://www.cnblogs.com/liyu3519/p/6889076.html
Copyright © 2020-2023  润新知