可能是 C# 中使用最简单的 TCP 通讯包

348 阅读3分钟

前言

如果在项目中需要使用到 TCP 通讯,那么我推荐使用以下 TCP 通讯包

SimpleTCP

SuperSimpleTcp

WatsonTcp

项目地址

github.com/BrandonPott…

github.com/jchristn/Su…

github.com/dotnet/Wats…

针对不同的使用场景灵活选用;

都可以用网络调试助手 NetAssist 来调试

正文

如果只是发送简单的文本消息,推荐使用 SimpleTCP,上手超级简单;

简单使用,注册服务端三个事件(客户端连接、断开,收到客户端发来的消息),客户端一个事件(收到服务端发来的消息),分隔符和解码格式默认就好;

private SimpleTcpServer Server { getset; }
private SimpleTcpClient Client { getset; }

public MainWindow()
{
    InitializeComponent();

    Server = new SimpleTcpServer
    {
        Delimiter = 0x13,
        StringEncoder = Encoding.UTF8,
    };

    Client = new SimpleTcpClient
    {
        Delimiter = 0x13,
        StringEncoder = Encoding.UTF8,
    };

    Server.ClientConnected += ClientConnected;
    Server.ClientDisconnected += ClientDisconnected;
    Server.DataReceived += ServerDataReceived;

    Client.DataReceived += ClientDataReceived;
}

private void ClientDataReceived(object sender, Message e)
{
    PrintLog("Message from server: " + e.MessageString);
    //PrintLog("Message from server: " + Encoding.UTF8.GetString(e.Data));
}

private void ServerDataReceived(object sender, Message e)
{
    PrintLog("Message from client: " + e.MessageString);
}

private void ClientDisconnected(object sender, TcpClient e)
{
    PrintLog("Client disconnected: " + e.Client.RemoteEndPoint.ToString());
}

private void ClientConnected(object sender, TcpClient e)
{
    PrintLog("Client connected: " + e.Client.RemoteEndPoint.ToString());
}

private void PrintLog(string msg)
{
    Dispatcher.Invoke(() =>
    {
        lb.Items.Add(msg);
    });
}

private void OnStartServer(object sender, RoutedEventArgs e)
{
    if (!Server.IsStarted)
    {
        Server.Start(IPAddress.Parse("127.0.0.1"), 502);
    }
}

private void OnServerSendMessage(object sender, RoutedEventArgs e)
{
    Server.Broadcast("Hello, client!");
}


private void OnConnectServer(object sender, RoutedEventArgs e)
{
    Client.Connect("127.0.0.1"502);
}

private void OnClientSendMessage(object sender, RoutedEventArgs e)
{
    Client.Write("Hello, server!");
}

SuperSimpleTcp 稍微复杂点,客户端增加了两个事件(服务端连接、断开);

每个客户端连接时会有一个 Guid,服务端发送消息时需要指定 Guid;

增加了异步发送消息;

private SimpleTcpServer Server { getset; } = new SimpleTcpServer("127.0.0.1"502);
private SimpleTcpClient Client { getset; } = new SimpleTcpClient("127.0.0.1"502);
private string ClientGuid { getset; } = "";

public MainWindow()
{
    InitializeComponent();

    Server.Events.ClientConnected += ClientConnected;
    Server.Events.ClientDisconnected += ClientDisconnected;
    Server.Events.DataReceived += DataReceived;

    Client.Events.Connected += Connected;
    Client.Events.Disconnected += Disconnected;
    Client.Events.DataReceived += DataReceived;
}

private void PrintLog(string msg)
{
    Dispatcher.Invoke(() =>
    {
        lb.Items.Add(msg);
    });
}

private void Disconnected(object? sender, ConnectionEventArgs e)
{
    PrintLog($"*** Server {e.IpPort} disconnected");
}

private void Connected(object? sender, ConnectionEventArgs e)
{
    PrintLog($"*** Server {e.IpPort} connected");
}

private void DataReceived(object? sender, DataReceivedEventArgs e)
{
    PrintLog($"[{e.IpPort}{Encoding.UTF8.GetString(e.Data.Array, 0, e.Data.Count)}");
}

private void ClientDisconnected(object? sender, ConnectionEventArgs e)
{
    Console.WriteLine($"[{e.IpPort}] client disconnected: {e.Reason}");
    ClientGuid = "";
}

private void ClientConnected(object? sender, ConnectionEventArgs e)
{
    Console.WriteLine($"[{e.IpPort}] client connected");
    ClientGuid = e.IpPort;
}

private void OnStartServer(object sender, RoutedEventArgs e)
{
    if (!Server.IsListening)
    {
        Server.Start();
    }
}

private async void OnServerSendMessage(object sender, RoutedEventArgs e)
{
    Server.Send(ClientGuid, "Hello, client!");

    await Server.SendAsync(ClientGuid, "Hello, client!");
}

private void OnConnectServer(object sender, RoutedEventArgs e)
{
    if (!Client.IsConnected)
    {
        Client.Connect();
    }
}

private async void OnClientSendMessage(object sender, RoutedEventArgs e)
{
    Client.Send("Hello, server!");

    await Client.SendAsync("Hello, server!");
}

WatsonTcp 貌似只能异步发送消息,服务端和客户端多加了一个事件(发出消息后等待返回消息);

可以发送 Metadata 数据;

private WatsonTcpServer Server { getset; } = new WatsonTcpServer("127.0.0.1"502);
private WatsonTcpClient Client { getset; } = new WatsonTcpClient("127.0.0.1"502);
private Guid ClientGuid { getset; } = Guid.Empty;

public MainWindow()
{
    InitializeComponent();

    Server.Events.ClientConnected += ClientConnected;
    Server.Events.ClientDisconnected += ClientDisconnected;
    Server.Events.MessageReceived += MessageReceivedFromClient;
    Server.Callbacks.SyncRequestReceivedAsync = SyncRequestReceived;

    Client.Events.ServerConnected += ServerConnected;
    Client.Events.ServerDisconnected += ServerDisconnected;
    Client.Events.MessageReceived += MessageReceivedFromServer;
    Client.Callbacks.SyncRequestReceivedAsync = SyncRequestReceived;
}

private void PrintLog(string msg)
{
    Dispatcher.BeginInvoke(() =>
    {
        lb.Items.Add(msg);
    });
}

private void ClientConnected(object sender, ConnectionEventArgs args)
{
    ClientGuid = args.Client.Guid;
    PrintLog("Client connected: " + args.Client.ToString());
}
private void ClientDisconnected(object sender, DisconnectionEventArgs args)
{
    ClientGuid = Guid.Empty;
    PrintLog("Client disconnected: " + args.Client.ToString() + ": " + args.Reason.ToString());
}
private void MessageReceivedFromClient(object sender, MessageReceivedEventArgs args)
{
    PrintLog("Message from " + args.Client.ToString() + ": " + Encoding.UTF8.GetString(args.Data));
    if (args.Metadata != null)
    {
        foreach (var item in args.Metadata)
        {
            PrintLog("Metadata from client: key = " + item.Key + ", value = " + item.Value);
        }
    }
}

#pragma warning disable CS1998 // 异步方法缺少 "await" 运算符,将以同步方式运行
        private async Task<SyncResponse> SyncRequestReceived(SyncRequest req)
#pragma warning restore CS1998 // 异步方法缺少 "await" 运算符,将以同步方式运行
        {
            PrintLog(Encoding.UTF8.GetString(req.Data));
            return new SyncResponse(req, "Hello back at you!");
        }

        private void ServerConnected(object sender, ConnectionEventArgs args)
        {
            PrintLog("Server connected");
        }

        private void ServerDisconnected(object sender, DisconnectionEventArgs args)
        {
            PrintLog("Server disconnected");
        }

        private void MessageReceivedFromServer(object sender, MessageReceivedEventArgs args)
        {
            PrintLog("Message from server: " + Encoding.UTF8.GetString(args.Data));
            if (args.Metadata != null)
            {
                foreach (var item in args.Metadata)
                {
                    PrintLog("Metadata from server: key = " + item.Key + ", value = " + item.Value);
                }
            }
        }


        private void OnStartServer(object sender, RoutedEventArgs e)
        {
            if (!Server.IsListening)
            {
                Server.Start();
            }
        } 

        private async void OnServerSendText(object sender, RoutedEventArgs e)
        {
            await Server.SendAsync(ClientGuid, "Hello, client!");
        }

        private async void OnServerSendMetadata(object sender, RoutedEventArgs e)
        {
            Dictionary<stringobject> md = new Dictionary<stringobject>
            {
                { "foo""bar" }
            };
            await Server.SendAsync(ClientGuid, "Hello, client!  Here's some metadata!", md);
        }

private async void OnServerSendAndResponse(object sender, RoutedEventArgs e)
{
    try
    {
        SyncResponse resp = await Server.SendAndWaitAsync(5000, ClientGuid, "Hey, say hello back within 5 seconds!");
        PrintLog("My friend says: " + Encoding.UTF8.GetString(resp.Data));
    }
    catch (TimeoutException)
    {
        PrintLog("Too slow...");
    }
}

private void OnConnectServer(object sender, RoutedEventArgs e)
{
    if (!Client.Connected)
    {
        Client.Connect();
    }
}

private async void OnClientSendText(object sender, RoutedEventArgs e)
{
    await Client.SendAsync("Hello, server!");
}

private async void OnClientSendMetadata(object sender, RoutedEventArgs e)
{
    Dictionary<stringobject> md = new Dictionary<stringobject>
    {
        { "foo""bar" }
    };
    await Client.SendAsync("Hello, server!  Here's some metadata!", md);
}

private async void OnClientSendAndResponse(object sender, RoutedEventArgs e)
{
    try
    {
        SyncResponse resp = await Client.SendAndWaitAsync(5000"Hey, say hello back within 5 seconds!");
        PrintLog("My friend says: " + Encoding.UTF8.GetString(resp.Data));
    }
    catch (TimeoutException)
    {
        PrintLog("Too slow...");
    }
}

当然,以上都是最简单的使用,还有更多功能等待探索,不过应对一般的使用场景还是搓搓有余了

最后

如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。

也可以加入微信公众号 [DotNet技术匠] 社区,与其他热爱技术的同行一起交流心得,共同成长!

优秀是一种习惯,欢迎大家留言学习!

作者:程序猿老王

出处:zhuanlan.zhihu.com/p/690746144

声明:网络内容,仅供学习,尊重版权,侵权速删,歉意致谢!