欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

.Net TCP探索(一)——TCP服务端开发(同时监听多个客户端请求)

程序员文章站 2022-06-11 17:20:21
    最近在园子里看了大神写的( "面试官,不要再问我三次握手和四次挥手" ),忍不住写段程序来测试一番。     在网上找了很多例子,大多只实现了TCP点对点通讯,但实际应用中,一个服务器端口往往要监听多个客户端发来 ......

    最近在园子里看了大神写的(),忍不住写段程序来测试一番。

    在网上找了很多例子,大多只实现了tcp点对点通讯,但实际应用中,一个服务器端口往往要监听多个客户端发来的消息。

测试工具下载:
    本例采用system.threading实现多线程监听,下面只介绍核心代码,省略了消息提示和错误处理,可以从我的github获取完整代码:https://github.com/fb208/codespace/tree/master/codespace.csharp/tcp.client

数据声明:

private string _ip;//ip
private int _port;//端口
//客户端集合
public static list<tcpclientmodel> clients = new list<tcpclientmodel>
private static byte[] bytes = new byte[1024 * 100];
/// <summary>
/// 用于存储客户端
/// </summary>
public class tcpclientmodel
{
    /// <summary>
    /// ip:port
    /// </summary>
    public string remoteendpoint { get; set; }
    /// <summary>
    /// 客户端链接对象
    /// </summary>
    public tcpclient tcpclient { get; set; }
}

启动监听:

///启动监听
void init()
{
    try
    {
        ipaddress ip = ipaddress.parse(_ip);
        int port = _port;
        tcplistener listener = new tcplistener(ip, port);
        //启动监听
        listener.start();
        tb_console.appendtext($"listener...\r\n");
        //异步接收 递归循环接收多个客户端
        listener.beginaccepttcpclient(new asynccallback(getaccepttcpclient), listener);
    }
    catch (exception ex)
    {
        
    }
}

接收客户端:

private void getaccepttcpclient(iasyncresult state)
{
    //处理多个客户端接入
    tcplistener listener = (tcplistener)state.asyncstate;
    //接收到客户端请求
    tcpclient client = listener.endaccepttcpclient(state);
    //保存到客户端集合中
    clients.add(new tcpclientmodel() { tcpclient = client, remoteendpoint = client.client.remoteendpoint.tostring() });

    //开启线程用来持续接收来自客户端的数据
    thread mythread = new thread(() =>
    {
        receivemsgfromclient(client);
    });
    mythread.start();
    listener.beginaccepttcpclient(new asynccallback(getaccepttcpclient), listener);
}

接收消息并响应客户端:

private void receivemsgfromclient(object reciveclient)
{
    tcpclient client = reciveclient as tcpclient;
    if (client == null)
    {
        return;
    }
    while (true)
    {
        try
        {
            networkstream stream = client.getstream();
            int num = stream.read(bytes, 0, bytes.length); //将数据读到result中,并返回字符长度                  
            if (num != 0)
            {
                //把字节数组中流存储的数据以字符串方式赋值给str
                //这里就是接收到的客户端消息
                string str = encoding.utf8.getstring(bytes, 0, num);

                //给客户端返回一个消息
                string msg = "your message has been received by the server[" + str + "]";

                bool result = tcphelper.sendtoclient(client, msg, out msg);
                if (!result)
                {
                    //发送失败
                }
            }
            else
            {   
                //这里需要注意 当num=0时表明客户端已经断开连接,需要结束循环,不然会死循环一直卡住
                break;
            }
        }
        catch (exception ex)
        {
            //链接失败 从集合中移除出错客户端
            clients.remove(clients.firstordefault(m => m.remoteendpoint == client.client.remoteendpoint.tostring()));
            break;
        }

    }
}

从服务器向客户端发送消息的工具类:

public static class tcphelper
{
    public static bool sendtoclient(tcpclient client, string message,out string errormsg)
    {
        try
        {
            byte[] bytes = new byte[1024 * 100];
            bytes = encoding.utf8.getbytes(message);
            networkstream stream = client.getstream();
            stream.write(bytes, 0, bytes.length);
            stream.flush();
            errormsg = "";
            return true;
        }
        catch (exception ex)
        {
            errormsg = ex.message;
            return false;
        }
    }
}

测试效果:
.Net TCP探索(一)——TCP服务端开发(同时监听多个客户端请求)

完整代码请关注:https://github.com/fb208/codespace/tree/master/codespace.csharp/tcp.client