前言
如果在项目中需要使用到 TCP 通讯,那么我推荐使用以下 TCP 通讯包
SimpleTCP
SuperSimpleTcp
WatsonTcp
项目地址
针对不同的使用场景灵活选用;
都可以用网络调试助手 NetAssist 来调试
正文
如果只是发送简单的文本消息,推荐使用 SimpleTCP,上手超级简单;
简单使用,注册服务端三个事件(客户端连接、断开,收到客户端发来的消息),客户端一个事件(收到服务端发来的消息),分隔符和解码格式默认就好;
private SimpleTcpServer Server { get; set; }
private SimpleTcpClient Client { get; set; }
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 { get; set; } = new SimpleTcpServer("127.0.0.1", 502);
private SimpleTcpClient Client { get; set; } = new SimpleTcpClient("127.0.0.1", 502);
private string ClientGuid { get; set; } = "";
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 { get; set; } = new WatsonTcpServer("127.0.0.1", 502);
private WatsonTcpClient Client { get; set; } = new WatsonTcpClient("127.0.0.1", 502);
private Guid ClientGuid { get; set; } = 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<string, object> md = new Dictionary<string, object>
{
{ "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<string, object> md = new Dictionary<string, object>
{
{ "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
声明:网络内容,仅供学习,尊重版权,侵权速删,歉意致谢!