python - 如何避免 UWP TCP 客户端的延迟?
问题描述
我正在尝试在 python 服务器(第一台 PC)和 UWP 客户端应用程序(第二台 PC)之间创建 TCP 客户端/服务器程序。我想模拟一个快速的 python 服务器,它每 10 毫秒发送一条消息,以及一个速度较慢的 UWP 应用程序,它的更新功能必须显示每 40 毫秒收到的最后一条消息。
为此,在 UWP 端,我创建了一个任务,它读取 python 发送的消息,将其保存在变量 ( this.message
) 中并打印它。该Update
函数读取此变量并每 40 毫秒打印一次(每次打印后等待 40 毫秒)。
客户端/服务器交换工作,但我得到一个奇怪的行为。该Update
函数有时会“阻塞”相同的值,请参见输出:
...
[Task] Message = 1105, Ts = 1626767660488
[Task] Message = 1106, Ts = 1626767660495
[Task] Message = 1107, Ts = 1626767660502
[Task] Message = 1108, Ts = 1626767660508
[Task] Message = 1109, Ts = 1626767660512
[Task] Message = 1110, Ts = 1626767660516
[Task] Message = 1111, Ts = 1626767660519
[Task] Message = 1112, Ts = 1626767660523
[Task] Message = 1113, Ts = 1626767660527
[Task] Message = 1114, Ts = 1626767660530
[Task] Message = 1115, Ts = 1626767660534
[Task] Message = 1116, Ts = 1626767660537
[Task] Message = 1117, Ts = 1626767660541
[Update] Message = 1107
[Task] Message = 1118, Ts = 1626767660546
[Task] Message = 1119, Ts = 1626767660551
[Task] Message = 1120, Ts = 1626767660554
[Task] Message = 1121, Ts = 1626767660558
[Task] Message = 1122, Ts = 1626767660562
[Update] Message = 1122
[Update] Message = 1122
[Task] Message = 1123, Ts = 1626767660693
[Task] Message = 1124, Ts = 1626767660697
[Task] Message = 1125, Ts = 1626767660701
[Task] Message = 1126, Ts = 1626767660705
[Task] Message = 1127, Ts = 1626767660708
[Task] Message = 1128, Ts = 1626767660712
[Task] Message = 1129, Ts = 1626767660716
[Task] Message = 1130, Ts = 1626767660720
[Task] Message = 1131, Ts = 1626767660724
[Task] Message = 1132, Ts = 1626767660727
[Task] Message = 1133, Ts = 1626767660731
[Task] Message = 1134, Ts = 1626767660735
[Task] Message = 1135, Ts = 1626767660739
[Task] Message = 1136, Ts = 1626767660742
[Task] Message = 1137, Ts = 1626767660746
[Update] Message = 1124
[Task] Message = 1138, Ts = 1626767660757
[Task] Message = 1139, Ts = 1626767660760
[Task] Message = 1140, Ts = 1626767660764
[Task] Message = 1141, Ts = 1626767660768
[Task] Message = 1142, Ts = 1626767660772
[Task] Message = 1143, Ts = 1626767660775
[Update] Message = 1143
[Task] Message = 1144, Ts = 1626767660834
[Task] Message = 1145, Ts = 1626767660841
[Task] Message = 1146, Ts = 1626767660848
[Task] Message = 1147, Ts = 1626767660856
[Task] Message = 1148, Ts = 1626767660862
[Task] Message = 1149, Ts = 1626767660869
[Task] Message = 1150, Ts = 1626767660875
...
蟒蛇方面:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('', 4444))
print("[SERVER TCP] Waiting connection ...")
sock.listen(1)
client_socket, address = sock.accept()
data = client_socket.recv(1024)
print(data)
print("[SERVER TCP] Connection done")
x = 0
while True:
x = x + 1
msg = f"{x}\n"
client_socket.send(msg.encode())
sys.stdout.write(msg)
time.sleep(0.01)
UWP 应用端 (MainPage.xaml.cs):
using System;
using System.IO;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using System.Threading.Tasks;
using System.Diagnostics;
namespace ClientUWP
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
volatile String message;
Task T;
public MainPage()
{
this.InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
this.StartClient();
this.Update();
}
private async void StartClient()
{
try
{
var streamSocket = new Windows.Networking.Sockets.StreamSocket();
var hostName = new Windows.Networking.HostName("192.168.1.50");
string PortNumber = "4444";
string request = "Hello, World!";
await streamSocket.ConnectAsync(hostName, PortNumber);
using (Stream outputStream = streamSocket.OutputStream.AsStreamForWrite())
{
using (var streamWriter = new StreamWriter(outputStream))
{
await streamWriter.WriteLineAsync(request);
await streamWriter.FlushAsync();
}
}
T = Task.Run(() =>
{
using (Stream inputStream = streamSocket.InputStream.AsStreamForRead())
{
using (StreamReader streamReader = new StreamReader(inputStream))
{
while (true)
{
this.message = streamReader.ReadLine();
Debug.WriteLine("[Task] Message = : " + this.message);
}
}
}
});
}
catch (Exception ex)
{
Windows.Networking.Sockets.SocketErrorStatus webErrorStatus = Windows.Networking.Sockets.SocketError.GetStatus(ex.GetBaseException().HResult);
Debug.WriteLine(webErrorStatus.ToString());
}
}
private async void Update()
{
while (true)
{
Debug.WriteLine("[Update] Message = " + this.message);
await Task.Delay(40);
}
T.Wait();
}
}
}
知道如何解决这个问题吗?谢谢!
更新帖子:
当我在 中打印时间戳时Task
,它似乎Task
冻结到Update
函数结束。
解决方案
您的数据本质上是随机输出。影响输出的原因有很多,例如网络延迟、CPU 使用率。比如你的网络延迟是160ms,在这160ms期间,你的客户端收不到消息,但是你的更新方法继续,导致连续出现4条更新消息。
因此,我建议您不要将这两个任务分开,您可以在一个任务中完成这些任务。您可以计算消息编号,而不是Task.Delay(40)
用来确定何时打印更新消息,换句话说,您可以每 40 条消息打印一条更新消息
推荐阅读
- elixir - 如何更改 Ecto 的调试颜色
- wix - Wix:为 .msp 创建 Bootstrap .exe 会导致原始版本卸载
- c# - 访问远程 com+ 对象时如何修复“80070005 访问被拒绝”?
- javascript - 仅取消 React 应用程序中的当前 axios 请求
- typescript - 如何访问类中函数内的类方法和属性
- azure - Azure IoT 中心中的消息路由只会导致孤立消息
- vba - 在同一个电子邮件中下载两个同名的附件
- firebase - 在 Firebase 控制台上删除 URL 前缀
- hybris - 促销未从 HMC 打开:de.hybris.platform.jalo.JaloSystemException:无法为项目创建 Jalo 实例
- docker - 为什么我在 docker 容器内的多解决方案 asp.net-core 应用程序中找不到 MSBuild