• C#开源类库SimpleTCP


    简介

    工作中经常遇到需要实现TCP客户端或服务端的时候,如果每次都自己写会很麻烦且无聊,使用SuperSocket库又太大了。这时候就可以使用SimpleTCP了,当然仅限于C#语言。

    SimpleTCP是一个简单且非常有用的 .NET 库,用于处理启动和使用 TCP 套接字(客户端和服务器)的重复性任务,使用起来非常方便、代码也少。它的内部不是直接使用的Socket,而是在TcpClient的基础上进行了再次封装,接口更简单、明了。

    它的主要特点如下:

    • 源码简单:源码就几个类,每个类也不大,在了解TcpClient用法的基础上不需要注释就可以看懂。
    • 功能单一:不像其它库一样功能繁多,它只专注于实现简单的TCP客户端、服务端,使用起来不用担心增加系统的复杂性。
    • 使用简单:后面的示例会具体讲解,启动一个客户端或服务端只需要几行代码,想扩展功能也很简单。

    说一下它的不足之处(在我看来完全可以接受):

    • 已停止更新:最后更新时间是2017年,不过库的功能比较简单、单一,也没那么多更新的内容。
    • 性能不是最优的:底层是基于TcpClient的,性能注定不会太高,但能用TcpClient的地方都可以用它。

    使用方法

    在项目中直接引用SimpleTCP.dll即可, dll文件可以通过NuGet安装或从github下载源码编译。
    SimpleTCP内部有一个特殊字符分割字符串的协议可以直接使用,也可以在DataReceived事件处理程序中实现自己的协议。

    实现客户端

    实现一个客户端的代码如下:

    //初始化
    var client = new SimpleTcpClient();            
    
    //设置编码格式,默认是UTF8
    client.StringEncoder = System.Text.ASCIIEncoding.ASCII;
    //设置分隔符,默认是0x13
    client.Delimiter = Encoding.ASCII.GetBytes("
    ")[0];
    
    //收到分割数据的事件,遇到分隔符就会触发事件
    client.DelimiterDataReceived += (sender, msg) => 
    {
        Console.WriteLine("DelimiterStr-"+DateTime.Now.ToString()+ msg.MessageString);
    };
    
    //收到数据的事件,可以在这里实现自己的协议
    client.DataReceived += (sender, msg) => 
    {
        //字节数组
        Console.WriteLine("Data:"+BitConverter.ToString(msg.Data));
        //字符串消息
        Console.WriteLine("ReceivedStr:" + msg.MessageString);
    };
    

    DelimiterDataReceivedDataReceived内部使用了两个不同的字节链表,解析起来互不影响。这两个事件的处理程序中尽量不要做耗时的操作,否则会影响后续的数据接收

    SimpleTCP没有心跳、重连功能,也没找到反馈客户端连接状态的属性(不建议使用内部TcpClient的连接状态)。我们可以直接扩展这些功能,代码如下:

    bool exit = false;
    bool connected = false;
    Task.Factory.StartNew(() => 
    {
        while (!exit) 
        {
            try
            {
                if (connected)
                {
                    //发送心跳
                    client.Write("");
                    Task.Delay(10000).Wait();
                }
                else
                {
                    //断线重连
                    client.Connect("127.0.0.1", 4196);
                    connected = true;
                    Task.Delay(1000).Wait();
                }
            }
            catch (Exception)
            {
                connected = false;
                client.Disconnect();
            }
        }               
        
    }, TaskCreationOptions.LongRunning);
    

    把上面的代码按顺序复制到控制台的Main函数中,然后加入下面的代码就可以收发数据了:

    while (true) 
    {
        string strLine = Console.ReadLine();
        if (strLine == "esc") 
        {
            exit = true;
            client.Disconnect();
            return;
        }
        if (connected) 
        { 
            //获取服务端回复的消息,最多等待3秒,收到消息时会提前返回
            //也可以使用Write、WriteLine方法发送数据,WriteLine会自动在后面加上设置的分隔符
            var replyMsg = client.WriteLineAndGetReply(strLine, TimeSpan.FromSeconds(3));
            if (replyMsg != null) 
            {
                Console.WriteLine(replyMsg);
            }
        }
    }
    

    注:WriteLineAndGetReply内部使用的是DataReceived,不会自动去除分隔符

    实现服务端

    服务端功能比较简单,把收到分割数据加工后返回客户端,代码如下:

    //初始化
    var server = new SimpleTcpServer();
    //设置编码格式,默认是UTF8
    server.StringEncoder = System.Text.ASCIIEncoding.ASCII;
    server.Delimiter =  Encoding.ASCII.GetBytes("
    ")[0];
    
    //分割数据接收事件
    server.DelimiterDataReceived += (sender, msg) => 
    {
        Console.WriteLine(msg.TcpClient.Client.RemoteEndPoint.ToString()+":" + msg.MessageString);
        msg.ReplyLine("Reply-" + msg.MessageString);
    };
    
    //数据接收数据
    server.DataReceived += (sender, msg) =>
    {
        Console.WriteLine(msg.TcpClient.Client.RemoteEndPoint.ToString() + ":" + msg.MessageString);
    };
    
    //客户端连接事件
    server.ClientConnected += (sender, msg) => 
    {
        Console.WriteLine("ClientConnected:" + msg.Client.RemoteEndPoint.ToString());
    };
    
    //客户端断开事件
    server.ClientDisconnected += (sender, msg) =>
    {
        Console.WriteLine("ClientDisconnected:" + msg.Client.RemoteEndPoint.ToString());
    };
    
    //开始监听
    server.Start(4196);
    //监听的IP
    var listeningIps = server.GetListeningIPs();
    //监听的V4Ip
    var listeningV4Ips = server.GetListeningIPs().Where(ip => ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork);
    
    
    
    Task.Factory.StartNew(() =>
    {
        while (true)
        {   
            //连接数监控
            int clientsConnected = server.ConnectedClientsCount;
            Console.WriteLine("当前连接的客户端数:" + clientsConnected);
            Task.Delay(10000).Wait();
        }
    
    }, TaskCreationOptions.LongRunning);            
    Console.ReadLine();
    
    //停止监听
    server.Stop();
    Console.WriteLine("停止服务端!");
    Console.ReadLine();
    

    总结

    上面的代码主要为了展示库的功能,实际使用时可能就几行代码,性能要求不高的项目都可以使用。

    项目和库的源码链接如下:

  • 相关阅读:
    接竹竿
    Vijos P1053 Easy SSSP
    计算机网络-五层协议和物理层
    代码阅读
    selenium自动化测试原理和设计的分享
    appium desktop 1.7 byName不能用,重写
    appium desktop 1.7 的swipe功能不能用,重写。
    appium在不同类中使用的是同一个session
    GIT 上传、ssh设置、一些命令。
    java 学习:在java中启动其他应用,由jenkins想到的
  • 原文地址:https://www.cnblogs.com/timefiles/p/CSharpSimpleTCP.html
Copyright © 2020-2023  润新知