Вопрос по sockets, .net, c#, asynchronous – Сброс соединения при получении пакета на сервере UDP

6

Я работаю над серверным приложением (C #, .NET 4.0), которое должно обрабатывать тысячи пакетов UDP каждую секунду. Поэтому я решилSocketAsyncEventArg реализовать сервер.

Проблема, с которой я сталкиваюсь, заключается в том, что моя реализация получает только один пакет, а затем я получаю & quot; ConnectionReset & quot; ошибка (я никогда не думал, что смогу получить эту ошибку, потому что UDP не использует соединение). Вот моя тестовая реализация:

<code>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();
    }
}
</code>

Извините за длинный код, но это действительно просто. Я жду пакета, отвечаю на удаленную конечную точку и затем жду следующего. Вот вывод:

<code>ReceiveNext

SendPacket
Receive Complete: Success
Sending reply packet
Send Complete: Success
ReceiveNext
Error in ReceiveNext: ConnectionReset
</code>

Подскажите, пожалуйста, что не так в приведенном выше фрагменте кода?

Ваш Ответ

2   ответа
11

что вам нужно сделать, это изменитьрежим работы сокета прежде чем связать это. Используйте этот код в своемStart метод.

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);
Просто так оно и есть - какой-то разработчик разработал это так, и мы должны следовать :-)
Это работает, большое спасибо за обмен. Я работаю над курсом программирования сокетов UDP и столкнулся с той же проблемой. Добавление вашего кода ко мне решает проблему, но я не знаю, как это произошло. Было бы здорово, если бы вы могли объяснить немного больше о том, как и почему это работает?
Спасибо за ответ, не могли бы вы объяснить, пожалуйста?
1

Close наUdpClient тогда программа работает как положено. Почему это происходит, я не уверен, но это может быть связано с петлевой сетью Windows.

Да. Вы правы. Что более интересно, так это то, что если мы сохранимClose но запустить клиент и сервер на разных компьютерах, тогда проблема также решена. Как вы сказали, должно быть что-то с петлевым механизмом Windows. Hemant
Да, меня это не удивляет. Если закрытие сокета UDP на одном хосте вызвало закрытие сокета UDP на другом хосте, я бы начал беспокоиться!

Похожие вопросы