我有一个基本的C#.NET UDP服务器和客户端代码,我正在尝试将其移植到UWP。对于UWP,我尝试使用DatagramSocket和常规Socket类。我看到使用DatagramSocket类在UWP服务器上传入的UDP数据包上有近40%的数据包丢失。如果我使用UWP套接字,我看到丢包率约为70%。旧的.NET代码显示0%的数据包丢失。
我想也许我没有正确使用UWP API,因此我的性能很差。有人可以指导我如何提高UWP服务器的性能吗?
现在,所有测试都是使用环回来完成的。默认情况下,UWP不允许环回,因此我按照提到的here说明启用环回。
服务器在50000端口上侦听数据包,客户端代码从50001向服务器发送大约60字节的数据包。
C#.NET客户端代码如下:
try
{
byte[] buffer = new byte[1024];
IPEndPoint localEP = new IPEndPoint(IPAddress.Any, 50001);
IPAddress remoteIp = System.Net.IPAddress.Parse("127.0.0.1");
IPEndPoint remoteEP = new IPEndPoint(remoteIp, 50000);
Socket sender = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
try
{
sender.Bind(localEP);
for(int i = 0; i < 10000; i++)
{
//Thread.Sleep(1);
// Encode the data string into a byte array.
string ClientReq = "Client Request:: " + i.ToString() + " "+ Guid.NewGuid().ToString();
byte[] msg = Encoding.ASCII.GetBytes(ClientReq);
// Send the data through the socket.
int sentBytes = sender.SendTo(msg, remoteEP);
Console.WriteLine("{0}::{1} Client Request ({2} bytes):: {3}.",
remoteEP.Address.ToString(),
remoteEP.Port.ToString(),
sentBytes,
ClientReq
);
}
// Release the socket.
sender.Close();
//Console.ReadKey();
}
catch(ArgumentNullException ane)
{
Console.WriteLine("ArgumentNullException : {0}", ane.ToString());
}
catch(SocketException se)
{
Console.WriteLine("SocketException : {0}", se.ToString());
}
catch(Exception e)
{
Console.WriteLine("Unexpected exception : {0}", e.ToString());
}
}
catch(Exception e)
{
Console.WriteLine(e.ToString());
}
C#.NET服务器代码:
byte[] buffer = new Byte[1024];
IPAddress LocalIp = IPAddress.Any; //System.Net.IPAddress.Parse("127.0.0.1");
IPEndPoint localEndPoint = new IPEndPoint(LocalIp, 50000);
// Create a UDP/IP socket.
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp );
// Bind the socket to the local endpoint and
// listen for incoming connections.
try
{
listener.Bind(localEndPoint);
Console.WriteLine("Bind Complete");
int messagesReceived = 0;
while(true)
{
EndPoint receiveEP = new IPEndPoint(IPAddress.Any, 0);
int receivedBytes = listener.ReceiveFrom(buffer, ref receiveEP);
messagesReceived++;
IPEndPoint receiveIPEP = receiveEP as IPEndPoint;
Console.WriteLine("{0}::{1}::{2} Client Request ({3} bytes):: {4}.",
messagesReceived,
receiveIPEP.Address.ToString(),
receiveIPEP.Port.ToString(),
receivedBytes,
System.Text.Encoding.UTF8.GetString(buffer, 0, receivedBytes));
}
}
catch(Exception e)
{
Console.WriteLine(e.ToString());
}
使用上面的代码,我看到服务器上收到了所有10000个数据包。
UWP DatagramSocket Code:
DgSocket = new DatagramSocket();
DgSocket.MessageReceived += SocketListener_MessageReceived;
await DgSocket.BindServiceNameAsync("50000");
private async void SocketListener_MessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
{
uint datalen = args.GetDataReader().UnconsumedBufferLength;
DataReader reader = args.GetDataReader();
byte[] dataBuffer = new byte[reader.UnconsumedBufferLength];
reader.ReadBytes(dataBuffer);
await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
lock(_lockObject)
{
DgPackets++;
DgPacketList.Add(Encoding.ASCII.GetString(dataBuffer));
}
});
}
UWP套接字代码:
public void SetupSimpleSocketListener()
{
try
{
IPAddress LocalIp = IPAddress.Any;
IPEndPoint localEndPoint = new IPEndPoint(LocalIp, 50000);
SimpleSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp );
byte[] buffer = new Byte[1024];
SimpleSocket.Bind(localEndPoint);
Debug.WriteLine("Bind Complete");
SocketAsyncEventArgs sockarg = new SocketAsyncEventArgs();
sockarg.Completed += Sockarg_Completed;
sockarg.RemoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
sockarg.SetBuffer(buffer, 0, buffer.Length);
if(!SimpleSocket.ReceiveFromAsync(sockarg))
{
Sockarg_Completed(this, sockarg);
}
}
catch(Exception e)
{
Debug.WriteLine(e.ToString());
}
}
private async void Sockarg_Completed(object sender, SocketAsyncEventArgs e)
{
await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
lock(_lockObject)
{
SimpleSocketPackets++;
SimpleSocketPacketList.Add(Encoding.ASCII.GetString(e.Buffer, 0, e.BytesTransferred));
}
});
if(e.SocketError == System.Net.Sockets.SocketError.Success)
{
if(!SimpleSocket.ReceiveFromAsync(e))
{
Sockarg_Completed(this, e);
}
}
}
我已在github上发布了完整的源代码: