使用UWP DatagramSocket& amp;套接字API

时间:2017-09-28 06:17:24

标签: c# sockets networking uwp udp

我有一个基本的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上发布了完整的源代码:

0 个答案:

没有答案