C # SocketAsyncEventArgs not sending all data

I have a problem with the SocketAsyncEventArgs class. The problem is that I try to send 8K data, for example, over the Internet, the socket sometimes sends only 1K or 2K, I know that this is normal for TCP, and the one that is sent does not guarantee receipt. now for this to work for me, I changed my code to resend the remaining data, for example when I SocketAsyncEventArgs.SendAsync is completed, in the callback I check whether it sent all 8K or not, if it is not, I call again SocketAsyncEventArgs.SendAsync with the remaining data until I send it all. Now that I have looked at some SocketAsyncEventArgs code .. I saw that most people do not! and they just get cleared when sending is complete without checking if it sent all the data or not! also,when I looked at the Microsoft example, they said that one call to SocketAsyncEventArgs.SendAsync ensures that all data is sent. I mean, I tested it myself, and none of this data will be sent with a single call to SocketAsyncEventArgs.SendAsync. What am I doing wrong? thanks in advance.

Edit: Here is a code that does not send all the data (just like Microsoft) SendAsyncComplete will be called when the socket sends, for example, 1Kb of data is not all 8K!

public virtual void Send(byte[] packet, int offset, int length)
{
    if (_tcpSock != null && _tcpSock.Connected)
    {
        var args = SocketHelpers.AcquireSocketArg();
        if (args != null)
        {
            args.Completed += SendAsyncComplete;
            args.SetBuffer(packet, offset, length);
            args.UserToken = this;

            var willRaiseEvent = _tcpSock.SendAsync(args);
            if (!willRaiseEvent)
            {
            ProcessSend(args);
            }
            unchecked
            {
                _bytesSent += (uint)length;
            }
            Interlocked.Add(ref _totalBytesSent, length);
        }
        else
        {
            log.Error("Client {0} SocketArgs are null", this);
        }
    }
}

private static void ProcessSend(SocketAsyncEventArgs args)
{
      args.Completed -= SendAsyncComplete;
      SocketHelpers.ReleaseSocketArg(args);   
}

private static void SendAsyncComplete(object sender, SocketAsyncEventArgs args)
{
    ProcessSend(args);
}
+5
source share
1 answer

There are many things that I would change there. Read this as a preamble .

First of all, whenever you send any data on a socket, you must handle this event: either stop the entire sending process, or perform another send socket operation to send the remaining data.

So, it makes sense to have 3 methods, for example:

// This is the Send() to be used by your class' clients
1) public void Send(byte[] buffer);

, , , () SocketAsyncEventArgs, :

2) private void Send(SocketAsyncEventArgs e);

  Socket.SendAsync(SocketAsyncEventArgs e) (, ?) SAEA. - , (2) , , . , SAEA.

3) private void ProcessSent(SocketAsyncEventArgs e);

, . , SAEA . , (2) . , SAEA.BytesTransferred. , , ( "this" ).

SocketError SAEA.

:

  • , :

        // Attempt to send data in an asynchronous fashion
        bool isAsync = this.Socket.SendAsync(e);
    
        // Something went wrong and we didn't send the data async
        if (!isAsync)
            this.ProcessSent(e);
    

, Begin/EndXXX ( IAsyncResult). , ( ) StackOverflow .

  • :

    private void Completed(object sender, SocketAsyncEventArgs e)
    {
        // What type of operation did just completed?
        switch (e.LastOperation)
        {
            case SocketAsyncOperation.Send:
                {
                    ProcessSent(e);
                    break;
                }
        }
    }
    

SocketAsyncEventArgs 1- (byte []) 3- , .

( ) SocketAsyncEventArgs.UserToken , , Socket.SendAsync().

, , , SAEA, Send() Receive(), . , : ( ) .

, 1st Send(), , . , , Send (byte []) " " Socket.SendAsync(), , 1- . , . -, " " , send op - . concurrency .

, , , , . SocketAsyncEventArgs, , .

, , , .

Edit:

,

unchecked
{
    _bytesSent += (uint)length;
}
Interlocked.Add(ref _totalBytesSent, length);

ProcessSend (SAEA) args.BytesTransferred "length".

+5

All Articles