SuperSocket.ClientEngine icon indicating copy to clipboard operation
SuperSocket.ClientEngine copied to clipboard

System.InvalidOperationException was thrown when sending data with EasyClient

Open wmjordan opened this issue 8 years ago • 11 comments

I was using the easy client to send some data. The source data was pushed into the application from about 20 incoming TCP connections, processed by a AppServer of SocketEngine, which called an EasyClient to send data to another place. The client was under a pretty low workload, sending about 2 packages a second only. However, it occasionally threw a "System.InvalidOperationException" and the application became unusable afterward.

The following was the stack trace related to the exception. I could not found a line relative to my own code, I deduced that it was in another thread, spawned from the EasyClient.

System.InvalidOperationException: "An asynchronous socket operation is already in progress using this SocketAsyncEventArgs instance.";
SuperSocket.ClientEngine.AsyncTcpSession.SetBuffer(ArraySegment`1 bufferSegment) @ SuperSocket.ClientEngine\Core\AsyncTcpSession.cs[36:13]
SuperSocket.ClientEngine.ClientSession.SuperSocket.ClientEngine.IBufferSetter.SetBuffer(ArraySegment`1 bufferSegment) @ SuperSocket.ClientEngine\Core\ClientSession.cs[207:13]
SuperSocket.ClientEngine.EasyClientBase.OnSessionDataReceived(Object sender, DataEventArgs e) @ SuperSocket.ClientEngine\EasyClientBase.cs[236:13]
SuperSocket.ClientEngine.AsyncTcpSession.ProcessReceive(SocketAsyncEventArgs e) @ SuperSocket.ClientEngine\Core\AsyncTcpSession.cs[89:13]

wmjordan avatar Mar 10 '17 02:03 wmjordan

Do you have a test case I can reproduce this issue?

kerryjiang avatar Mar 10 '17 03:03 kerryjiang

Thank you for replying. It was hard to reproduce in a short time. I was trying to mock up a stress test model to reproduce this issue and I would post it here when it is finished. Meanwhile, I moved the application to another machine and see whether it would occur there as well.

wmjordan avatar Mar 10 '17 03:03 wmjordan

And which version do you use?

kerryjiang avatar Mar 10 '17 04:03 kerryjiang

Sorry to have forgotten to mention the versions. All assemblies were compiled from the newest source code from your repositories. I'd removed the dependency from NuGet and used the compiled assemblies in the ClientEngine project.

wmjordan avatar Mar 10 '17 06:03 wmjordan

The projects targeting .NET 4.0 were used to compile the assemblies. And the operating system was Windows Server 2008.

wmjordan avatar Mar 10 '17 07:03 wmjordan

I studied the source code of EasyClientBase and AsyncTcpSession.

I found that the AsyncTcpSession.SendInternal, AsyncTcpSession.StartReceive and AsyncTcpSession.SetBuffer can be using the same instance of SocketAsyncEventArgs without locking. However, the SocketAsyncEventArgs internally excludes data-sending, data-receiving and buffer-setting operations mutually. Those three operations can not proceed at the same time. Consequently, the SetBuffer method can fail when the Socket is using the SocketAsyncEventArgs instance to receive or send data and therefore the InvalidOperationException is thrown. Thread synchronization shall be deployed to avoid the above problem.

wmjordan avatar Mar 13 '17 01:03 wmjordan

I think send and receive have different SocketAsyncEventArgs instances: private SocketAsyncEventArgs m_SocketEventArgs; private SocketAsyncEventArgs m_SocketEventArgsSend;

kerryjiang avatar Mar 13 '17 07:03 kerryjiang

The issue happened to my applications when the client was attempting to receive data. Could it be possible that the SetBuffer method was called when a socket was using the same SocketAsyncEventArgs instance to receive data?

wmjordan avatar Mar 13 '17 08:03 wmjordan

Is there a way to produce this issue easily?

kerryjiang avatar Mar 13 '17 20:03 kerryjiang

Not so easy, I am afraid. But, I will still try to make a test case for you, or fix this issue at my side and commit a pull request here if I am lucky.

wmjordan avatar Mar 14 '17 04:03 wmjordan

重连多次,大概10次左右。 protected override void SetBuffer(ArraySegment bufferSegment) { base.SetBuffer(bufferSegment);

        if (m_SocketEventArgs != null)
        {
            m_SocketEventArgs.SetBuffer(bufferSegment.Array, bufferSegment.Offset, bufferSegment.Count);
        }
    }

m_SocketEventArgs.SetBuffer 这里报这个错误。连接上之后,已经在接收数据时候,报错。

yusliao avatar Jul 26 '18 01:07 yusliao