SocketException Операция над сокетом не может быть выполнена из-за того, что в системе недостаточно места в буфере или из-за того, что очередь переполнена.

откуда может быть эта проблема?

SocketException Операция над сокетом не может быть выполнена, так как в системе недостаточно места в буфере или очередь переполнена

Socket newsock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPEndPoint sender = new IPEndPoint(IPAddress.Any, 50509);
EndPoint tmpRemote = (EndPoint)(sender);

newsock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
newsock.Bind(ipep);

    while (thread_Listen == true && work == true)
        {
            try
            {
                Object state = new Object();
                **>> at this place >>** newsock.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref tmpRemote, new AsyncCallback(DoReceiveFrom), state);
                Array.Clear(buffer, 0, buffer.Length);
            }
            catch (SocketException ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

Вот как выглядит функция DoReceiveFrom

private void DoReceiveFrom(IAsyncResult iar)
{
    try
    {
        Socket recvSock = (Socket)iar.AsyncState;
        EndPoint clientEP = new IPEndPoint(IPAddress.Any, 0);
        int msgLen = recvSock.EndReceiveFrom(iar, ref clientEP);
        byte[] localMsg = GetAndCleanPacket(buffer);
        string[] packet = Encoding.ASCII.GetString(localMsg).Split(new Char[] { '|' });
        if (packet.Length > 0)
        {
            if (packet[0] == "ms")
            {
                // Connect
                if (packet[1] == "c") MSc(ip[0], packet[9], packet, clientEP);
                else if (packet[1] == "s") MSs(ip[0], packet);
                else if (packet[1] == "d") MDc(ip[0], packet);
            }
            else if (packet[0] == "p") ping(clientEP);
            else if (packet[0] == "sList") serverList(clientEP);
            else if (packet[0] == "bi") brGetInfo(packet, clientEP);
            else if (packet[0] == "error") AddError(packet[1], packet[2]);
        }
    }
    catch (InvalidOperationException)
    {
    }
    catch (SocketException)
    {
    }
    catch (Exception e)
    {
        errors.Add(e.ToString());
    }
}

person SLI    schedule 24.12.2011    source источник
comment
Какова длина буферного массива?   -  person Elastep    schedule 24.12.2011
comment
1024 пробовал 2048, но такое же исключение   -  person SLI    schedule 24.12.2011
comment
Как выглядит DoReceiveFrom?   -  person Damien_The_Unbeliever    schedule 24.12.2011


Ответы (2)


Ваш цикл while вызывает BeginReceiveFrom() с очень высокой скоростью. Пока операционная система не отключится и не откажется выделять больше ресурсов, не должно пройти более доли секунды.

Вам придется сделать это по-другому, вызывайте BeginReceiveFrom только после того, как вы что-то получили. В DoReceiveFrom().

person Hans Passant    schedule 24.12.2011

Что я делаю, так это использую класс StateObject, который содержит объект IAsyncResult. Это следует использовать как для TCP, так и для UDP. Вот пример для UDP.

    // Used for receiver to signal client that data has been received
    // 'readonly' for .Net 4.8
    private readonly ManualResetEvent receiveDone = new ManualResetEvent(false);

    /// <summary>
    /// Supports async receive on UDP socket
    /// </summary>
    private class StateObject
    {
        // Client socket.  
        public UdpClient workSocket = null;
        // Receive buffer.  
        public byte[] buffer;
        // Received data string.  
        public StringBuilder sb = new StringBuilder();
        //public int bytesRead;
        // receiver state
        public IAsyncResult result;

        public delegate void RecvMethod(IAsyncResult result);

        public void BeginReceive(RecvMethod recvMethod, UdpClient udpClient)
        {
            // Set the socket
            workSocket = udpClient;
            // start async receiver
            result = workSocket.BeginReceive(new AsyncCallback(recvMethod), this);
        }
    }

Метод Receive (вызываемый клиентским приложением) проверяет свое состояние и срабатывает только в том случае, если получатель не просигнализировал (используя ReceiveDone) и IAsyncResult.Completed имеет значение false.

Это ключевой момент: если приемник все еще активен, не запускайте его снова, иначе вы тратите системные ресурсы. Это требует еще одного сокета и буферной памяти, что укусит ваше приложение, обычно когда вы пытаетесь связаться с устройством, которое находится в автономном режиме.

    /// <summary>
    /// Set up async receive handler
    /// </summary>
    /// <returns></returns>
    public void Receive()
    {
        // if receiver running, no packet received - do not restart receiver!
        // did receiver signal done?
        if (receiveDone.WaitOne(0))
        {
            // yes - do not restart receiver!
        }
        // is receiver still running?
        else if (CurrentState.result != null && !CurrentState.result.IsCompleted)
        {
            // yes - do not restart receiver!
        }
        else
        {
            // Begin receiving the data from the remote device.
            CurrentState.BeginReceive(ReceiveCallback, udpClient);
        }
    }

Обратный вызов получения выглядит следующим образом:

    /// <summary>
    /// End receive (with blocking) and process received data into buffer
    /// </summary>
    /// <param name="ar">Information about the async operation</param>
    private void ReceiveCallback(IAsyncResult ar)
    {
        // Retrieve the state object and the client socket
        // from the asynchronous state object.
        StateObject st = ar.AsyncState as StateObject;
        UdpClient client = st.workSocket;

        try
        {
            st.buffer = client.EndReceive(ar, ref receivePoint);
            // Read data from the remote device.
            receiveDone.Set();
        }
        // Since this is a callback, catch any error
        // ObjectDisposedException has been seen
        catch (ObjectDisposedException)
        { }
        // "An existing connection was forcibly closed by remote host" has been seen
        // see https://stackoverflow.com/questions/38191968/c-sharp-udp-an-existing-connection-was-forcibly-closed-by-the-remote-host for further information
        catch
        {
        }
    }
person pwrgreg007    schedule 04.01.2021