Click here to Skip to main content
15,889,931 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
I'm writing a server application which uses the .net sockets to communicate using the provided Async functionality, and I have a question regarding the reliability of the method I am using.

MSDN - Socket.EndReceive Method (IAsyncResult)[^] Notes that:
"All I/O initiated by a given thread is canceled when that thread exits. A pending asynchronous operation can fail if the thread exits before the operation completes."

With this in mind, if I call my BeginRecieve() function from within the delegate that is called by BeginAccept(), Can I rely on the async receive function successfully completing, given that I have no control over the threadpool iocp uses in the background to run the socket async events?
(noob note: I'm still not 100% on exactly how it all goes together, please correct me if I am wrong)

Also, if it's not reliable, how would I be better off calling the receive function?

Thanks in advance.

basic outline of code:
C#
private void ClientAcceptorDelegate()
{
	while (AcceptingConnections)
	{
		//[omitted code]
		m_MainSocket.BeginAccept(new AsyncCallback(AcceptClientCallback), m_MainSocket);
		m_waitConnection.WaitOne();
		//[omitted code]
	}
}
void AcceptClientCallback(IAsyncResult AR)
{            
	Socket ClientSocket = (Socket) AR.AsyncState.EndAccept(AsyncResult);
	m_waitConnection.Set();

	//[omitted code]
	ClientStateMachine ClientState = new ClientStateMachine(clientName);

	ClientSocket.BeginReceive(ClientState.m_Recievebuffer, 0, ClientState.m_bufferSize, SocketFlags.None, new AsyncCallback(ClientRecieveDataCallback), ClientState);
	//NOTE: this __might__ fail? IO operations will terminate with the calling thread, if iocp worker thread dissapears this might never complete?. (nbdf)
	//[omitted code]
}
void ClientRecieveDataCallback(IAsyncResult AR) 
{
	ClientStateMachine ClientState = (ClientStateMachine) AR.AsyncState;
	Socket ClientSocket = ClientState.socket;
	int bytesRead=0;
	//[omitted code]
	bytesRead = ClientSocket.EndReceive(AR);
	//[omitted code]
	//continue recieve process
	ClientSocket.BeginReceive(ClientState.m_Recievebuffer, 0, ClientState.m_bufferSize, SocketFlags.None, new AsyncCallback(ClientRecieveDataCallback), ClientState);
}
Posted

1 solution

This is in VB.NET I wrote this several years ago and it has been running successfully without any issues for several years now in a client server application. I am sure it could use a good tune up, but it hasn't ever had any issues and it is heavily used transporting both textual data as well as binary files.


EDIT: Just noticed you were concerned about the beginreceive when the socket is first initialized so I am adding a bit more of the start of the socket receive code...


This is in my begin listening void for the server socket...

VB
'start accepting sockets Asynchronous
              tcpSocket.BeginAccept(New AsyncCallback(AddressOf Listening), Nothing)



This is my Listening() void for continued connection accepts...

Private Sub Listening(ByVal ar As IAsyncResult)
            Try
               
                If _connected = False Then

                    ar.AsyncWaitHandle.Close()

                    Exit Sub
                End If

                Dim syncSocket As System.Net.Sockets.Socket = tcpSocket.EndAccept(ar)

                'if socket connected as stop listener was initiated then terminate the socket
                If _connected = False Then
                    Try
                        syncSocket.Shutdown(SocketShutdown.Both)
                    Catch ex As Exception
                        RaiseEvent CommunicationExceptionEvent(New CustomNetSocketsException("Listening receive client on shutdown socket request Error: " & ex.Message, CustomNetSocketsException.ExceptionType.Generic))
                    End Try

                    syncSocket.Close()

                    Throw New CustomNetSocketsException("Listener was manually closed. Aborted socket connection")
                End If

                Dim syncDocu As New ChannelDocuEndPoint(syncSocket, channelProviders, AddressOf AddConnection, ccp)
               
                AddHandler syncDocu.CommunicationExceptionEvent, AddressOf DocuEndPoint_CommunicationExceptionEvent
                AddHandler syncDocu.CommunicationLinkEvent, AddressOf DocuEndPoint_CommunicationLinkEvent
                AddHandler syncDocu.DebugLoggingEvent, AddressOf DocuEndPoint_DebugLoggingEvent
                AddHandler syncDocu.ReceivedCommunicationEvent, AddressOf DocuEndPoint_ReceivedCommunicationEvent
                AddHandler syncDocu.Disposing, AddressOf DocuEndPoint_DisposingEvent

                syncDocu.Listen()

                tcpSocket.BeginAccept(New AsyncCallback(AddressOf Listening), Nothing)

            Catch eobj As ObjectDisposedException
                'closed

            Catch ex As Exception
                RaiseEvent CommunicationExceptionEvent(New CustomNetSocketsException(ex.Message, _
                    CustomNetSocketsException.ExceptionType.Generic))
            End Try
        End Sub


syncDocu.Listen()
syncDocu is a wrapper for socket. Inside the Listen() void is where I call the BeginReceive...


Private Sub Receive(ByVal state As Object)
               Dim arInt As Integer
               Dim ar As IAsyncResult
               Try

                   ar = DirectCast(state, IAsyncResult)

                   arInt = syncSocket.EndReceive(ar)

                   If Not disposedValue Then

                       RecSocketHandler = CType(ar.AsyncState, ISocketDataReceiver(Of IDocuEndPoint))
                       RecSocketHandler.Socket = Me
                       RecSocketHandler.SocketID = Me.ID

                       If arInt = 0 Then
                           'diconnected socket assumed
                           Throw New ObjectDisposedException("syncSocket", SocketError.Disconnecting.ToString)
                       End If

                       Dim readBuff(arInt - 1) As Byte

                       Array.Copy(Buffer, readBuff, arInt)

                       If readBuff.Length > 0 Then
                           RecSocketHandler.AppendData(readBuff)
                       End If

                       If RecSocketHandler.IsHeaderComplete Then
                           'we are good to go otherwise...
                           ReDim Buffer(65536)
                       Else
                           'adjust buffer to try and pick up the header
                           If RecSocketHandler.BytesReceived < 512 Then
                               ReDim Buffer((512 - RecSocketHandler.BytesReceived) - 1)
                           Else
                               'we have enough bytes for header but it isn't present???
                               Dispose()
                           End If
                       End If

                       Try
                           RecSocketHandler.RemoteEndPoint = syncSocket.RemoteEndPoint
                       Catch ex As Exception
                           RaiseEvent CommunicationExceptionEvent(New CustomNetSocketsException("Receive Exception: " & ex.Message & vbCrLf & ex.StackTrace, CustomNetSocketsException.ExceptionType.Generic))
                       End Try

                       If Not Me.disposedValue Then
                           syncSocket.BeginReceive(Buffer, 0, _
                           Buffer.Length, System.Net.Sockets.SocketFlags.None, New AsyncCallback(AddressOf QueueReceive), RecSocketHandler)
                       End If

                   End If

               Catch exs As SocketException
                   Dim err As SocketError = exs.NativeErrorCode
                   Select Case err
                       Case SocketError.ConnectionAborted
                           'we don't care about logging this error
                       Case SocketError.ConnectionReset
                           'we don't care about logging this error
                       Case SocketError.Disconnecting
                           'we don't care about logging this error
                       Case SocketError.HostDown
                           'we don't care about logging this error
                       Case Else
                           RaiseEvent CommunicationExceptionEvent(New CustomNetSocketsException("Socket Level Error: (" & exs.ErrorCode & " - " & err.ToString & ") " & exs.Message & vbCrLf & exs.StackTrace, CustomNetSocketsException.ExceptionType.SocketBase))
                   End Select

                   Dispose()
               Catch eobj As ObjectDisposedException
                   'closed

                   Dispose()
               Catch ex As Exception
                   RaiseEvent CommunicationExceptionEvent(New CustomNetSocketsException("Receive Exception: " & ex.Message & vbCrLf & ex.StackTrace, CustomNetSocketsException.ExceptionType.Generic))

                   Dispose()
               End Try
           End Sub
 
Share this answer
 
v2
Comments
Sandeep Mewara 4-Jul-12 2:25am    
My 5! Good direction provided.
cognismith 8-Jul-12 11:46am    
indirectly answered both my questions, thank you.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900