Hemant
Hemant

Reputation: 19826

Connection reset on receiving packet in UDP server

I am working on a server application (C#, .NET 4.0) that will need to handle thousands of UDP packets every second. So I decided to SocketAsyncEventArg to implement the server.

The problem I am facing is that my implementation receives just one packet and then I get "ConnectionReset" error (I never imagined I could get this error because UDP is connection-less). Here is my test implementation:

using System;
using System.Net;
using System.Net.Sockets;

static class Program
{
    static void Main(string[] args)
    {
        UdpEchoServer.Start();

        while (true)
        {
            Console.ReadLine();
            SendPacket();
        }
    }

    static void SendPacket()
    {
        Console.WriteLine("SendPacket");
        var c = new UdpClient();
        c.Send(new byte[5], 5, new IPEndPoint(IPAddress.Parse("127.0.0.1"), 445));
        c.Close();
    }
}

static class UdpEchoServer
{
    static Socket mSocket;
    static byte[] mBuffer;
    static SocketAsyncEventArgs mRxArgs, mTxArgs;
    static IPEndPoint mAnyEndPoint, mLocalEndPoint;

    public static void Start()
    {
        mAnyEndPoint = new IPEndPoint(IPAddress.Any, 0);
        mLocalEndPoint = new IPEndPoint(IPAddress.Any, 445);

        mBuffer = new byte[1024];

        mRxArgs = new SocketAsyncEventArgs();
        mTxArgs = new SocketAsyncEventArgs();

        mRxArgs.Completed += ReceiveComplete;
        mTxArgs.Completed += SendComplete;

        mSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
        mSocket.Bind(mLocalEndPoint);
        ReceiveNext();
    }

    static void ReceiveNext()
    {
        Console.WriteLine("ReceiveNext");

        mRxArgs.RemoteEndPoint = mAnyEndPoint;
        mRxArgs.SetBuffer(mBuffer, 0, mBuffer.Length);

        if (!mSocket.ReceiveFromAsync(mRxArgs))
            Console.WriteLine("Error in ReceiveNext: " + mRxArgs.SocketError);
    }

    static void ReceiveComplete(object sender, SocketAsyncEventArgs e)
    {
        Console.WriteLine("Receive Complete: " + mRxArgs.SocketError);

        if (mRxArgs.SocketError != SocketError.Success)
            return;

        mTxArgs.SetBuffer(mBuffer, 0, mRxArgs.BytesTransferred);
        mTxArgs.RemoteEndPoint = mRxArgs.RemoteEndPoint;

        Console.WriteLine("Sending reply packet");

        if (!mSocket.SendToAsync(mTxArgs))
            Console.WriteLine("Error in ReceiveComplete: " + mRxArgs.SocketError);
    }

    static void SendComplete(object sender, SocketAsyncEventArgs e)
    {
        Console.WriteLine("Send Complete: " + mTxArgs.SocketError);

        if (mTxArgs.SocketError != SocketError.Success)
            return;

        ReceiveNext();
    }
}

Sorry for long code but it is really simple. I wait for a packet, reply to remote end point and then wait for next one. Here is the output:

ReceiveNext

SendPacket
Receive Complete: Success
Sending reply packet
Send Complete: Success
ReceiveNext
Error in ReceiveNext: ConnectionReset

Please can you suggest what is wrong in above code snippet?

Upvotes: 6

Views: 6494

Answers (2)

Maciej
Maciej

Reputation: 7961

This happens with UDP sockets. All you need to do is change socket operating mode before binding it. Use this code in your Start method.

mSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

const int SIO_UDP_CONNRESET = -1744830452;
byte[] inValue = new byte[] {0};
byte[] outValue = new byte[] {0};
mSocket.IOControl(SIO_UDP_CONNRESET, inValue, outValue);

mSocket.Bind(mLocalEndPoint);

Upvotes: 15

Nick
Nick

Reputation: 25799

If you remove or comment out the call to Close on the UdpClient then the program works as expected. Why this is happening I'm not sure, but it could be to do with the Windows loopback networking.

Upvotes: 1

Related Questions