Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to 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:
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 3-Jul-12 18:44pm

1 solution

Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

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...
 
'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
  Permalink  
v2
Comments
Sandeep Mewara at 4-Jul-12 2:25am
   
My 5! Good direction provided.
cognismith at 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)

  Print Answers RSS
0 OriginalGriff 365
1 Sergey Alexandrovich Kryukov 329
2 CPallini 270
3 Afzaal Ahmad Zeeshan 204
4 DamithSL 194
0 OriginalGriff 5,515
1 DamithSL 4,451
2 Maciej Los 3,902
3 Kornfeld Eliyahu Peter 3,480
4 Sergey Alexandrovich Kryukov 3,175


Advertise | Privacy | Mobile
Web04 | 2.8.141216.1 | Last Updated 4 Jul 2012
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100