Let me preface this by saying I'm a novice coder at best. I've been tossed into doing this due to circumstances beyond control, so please forgive any ignorance.
I'm working on a listener service to work with the Avaya phone system as my company is switching to it. After poking around, I ended up basing most of my code on MS's example for asynchronous sockets. So far so good. Now, I'd like to add some manner of code when a timeout occurs (no data from Avaya for 5 minutes) to close any open connections and sockets and re-initialize to start listening again. The problem is, I'm unsure how to deal with the sockets in a multithreaded situation. Specifically how to determine if there are any open ports or connections, or any socket receiving data. The code thus far looks like this:
I've created a timer component to monitor the packettime variable for delays greater than 30 seconds and log an error (data should arrive every 10). At 5 minutes, I'd like to re-initialize the listener, but I'm not sure how to achieve that in the multithreaded environment. Can someone help me with an example of how to close any open ports and sockets, and I'm assuming just re-call the StartListening() sub? So far, any method I've tried to make sure all the sockets are closed just causes the service to hang, and just trying to call StartListening again results in errors because the port is in use.
I'm working on a listener service to work with the Avaya phone system as my company is switching to it. After poking around, I ended up basing most of my code on MS's example for asynchronous sockets. So far so good. Now, I'd like to add some manner of code when a timeout occurs (no data from Avaya for 5 minutes) to close any open connections and sockets and re-initialize to start listening again. The problem is, I'm unsure how to deal with the sockets in a multithreaded situation. Specifically how to determine if there are any open ports or connections, or any socket receiving data. The code thus far looks like this:
Code:
Public Shared allDone As New ManualResetEvent(False)
Public Shared listener As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
Public Shared Sub StartListening()
' Data buffer for incoming data.
Dim bytes() As Byte = New [Byte](1024) {}
' Establish Listener Endpoint Info
Dim ipHostInfo As IPHostEntry = Dns.Resolve(Dns.GetHostName())
localip = ipHostInfo.AddressList(0)
Dim localEndPoint As New IPEndPoint(localip, localport)
' Bind the socket to the local endpoint and listen for incoming connections.
Try
listener.Bind(localEndPoint)
listener.Listen(100)
While True
' Set the event to nonsignaled state.
allDone.Reset()
' Start an asynchronous socket to listen for connections.
If logging >= 1 Then
objStreamWriter = New StreamWriter(logpath & "collectorlog.txt", True)
objStreamWriter.WriteLine(Now() & " - Waiting for a connection...")
objStreamWriter.Close()
End If
listener.BeginAccept(New AsyncCallback(AddressOf AcceptCallback), listener)
' Wait until a connection is made before continuing.
allDone.WaitOne()
End While
Catch e As Exception
If logging >= 1 Then
objStreamWriter = New StreamWriter(logpath & "collectorlog.txt", True)
objStreamWriter.WriteLine(Now() & " - Error occured : " & e.ToString())
objStreamWriter.Close()
End If
End Try
End Sub 'StartListening
Public Shared Sub AcceptCallback(ByVal ar As IAsyncResult)
If logging >= 1 Then
objStreamWriter = New StreamWriter(logpath & "collectorlog.txt", True)
objStreamWriter.WriteLine(Now() & " - Connection accepted.")
objStreamWriter.Close()
End If
' Signal the main thread to continue.
allDone.Set()
' Get the socket that handles the client request.
Dim listener As Socket = CType(ar.AsyncState, Socket)
Dim handler As Socket = listener.EndAccept(ar)
' Create the state object.
Dim state As New StateObject
state.workSocket = handler
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, New AsyncCallback(AddressOf ReadCallback), state)
End Sub 'AcceptCallback
Public Shared Sub ReadCallback(ByVal ar As IAsyncResult)
Dim content As [String] = [String].Empty
' Retrieve the state object and the handler socket from the asynchronous state object.
Dim state As StateObject = CType(ar.AsyncState, StateObject)
Dim handler As Socket = state.workSocket
' Read data from client socket.
Dim bytesRead As Integer = handler.EndReceive(ar)
If bytesRead > 0 Then
' There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead))
' Check for end-of-file tag ("END_OF_RECORDS"). If not present, continue read.
content = state.sb.ToString()
If content.IndexOf("END_OF_RECORDS") > -1 Then
' All the data has been read from the client.
If logging >= 2 Then
objStreamWriter = New StreamWriter(logpath & "collectorlog.txt", True)
objStreamWriter.WriteLine(Now() & " - Data Received.")
objStreamWriter.Close()
End If
' Update packettime to now. Timer checks this.
packettime = Now()
' Send to parser/db insert module
db.dbUpdate(content)
' Clear State and Content Objects
state = New StateObject
content = Nothing
bytesRead = Nothing
state.workSocket = handler
' Respawn receiver for next packet
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, New AsyncCallback(AddressOf ReadCallback), state)
' Terminate this thread.
Thread.CurrentThread.Abort()
allDone.Close()
Else
' Not all data received. Get more.
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, New AsyncCallback(AddressOf ReadCallback), state)
End If
End If
End Sub 'ReadCallback
I've created a timer component to monitor the packettime variable for delays greater than 30 seconds and log an error (data should arrive every 10). At 5 minutes, I'd like to re-initialize the listener, but I'm not sure how to achieve that in the multithreaded environment. Can someone help me with an example of how to close any open ports and sockets, and I'm assuming just re-call the StartListening() sub? So far, any method I've tried to make sure all the sockets are closed just causes the service to hang, and just trying to call StartListening again results in errors because the port is in use.