programming4us
programming4us
ENTERPRISE

Microsoft Visual Basic 2008 : Services That Listen - Allowing Multiple Connections

- How To Install Windows Server 2012 On VirtualBox
- How To Bypass Torrent Connection Blocking By Your ISP
- How To Install Actual Facebook App On Kindle Fire
9/13/2012 12:58:07 AM
Allowing only a single connection might work, especially in cases where the requests come from either a single source or at intervals that help ensure that two resources cannot compete for a connection at the same time. However, in some circumstances a single instance of a service could be used to generate requests for multiple resources. A good example of this is when you have a server that is multi-homed for several subnets, and receives requests for data from any or all of these subnets—and possibly from multiple computers or processes on each subnet. In this case, a single point connection would not be beneficial; however, you still want to limit how many connections you allow for performance reasons.

Extending the Listener Class

This will require us to create up to 10 client sockets to accept the incoming requests, as well as telling our listener socket to accept up to 10 client requests before it returns an error to the client stating that it is unable to connect. Listener sockets only accept one socket at a time. Our code uses synchronous sockets with a backlog of up to 10 socket requests. Remember, though, that our configuration file allows us to specify the maximum number of sockets at any given time. Therefore, it is not a hard-coded value.

We’ll use ThreadPool to take care of the multiple connections that our class will now be able to accept. Let’s review the new modifications.

The <SocketThread> Method

We need to create a secondary thread method that will act as our socket processing thread. Since we will allow more than one connection at a time, having only a single thread won’t work. Listing 1 shows the newly created thread method.

Listing 1. The <SocketThread> thread method.
Private Sub SocketThread(ByVal args As Object)
    Dim lSocket As Socket = CType(args, Socket)
    Try
        Dim bytes() As Byte = New [Byte](1024) {}
        Dim Data As String = Nothing
        Dim bError As Boolean = False

        While Not m_ThreadAction.StopThread
            If Not m_ThreadAction.Pause Then
                Dim iStart As Long = Now.Ticks
                bytes = New Byte(1024) {}
                Dim bytesRec As Integer = lSocket.Receive(bytes)
                Data += Encoding.ASCII.GetString(bytes, 0, bytesRec)

                If ((Now.Ticks - iStart) / 10000000) > 30 Then
                    Try
                        lSocket.Shutdown(SocketShutdown.Both)
                    Catch ex As Exception
                    End Try

                    Try
                        lSocket.Close()
                    Catch ex As Exception
                    End Try

                    lSocket = Nothing
                    Exit Sub
                End If
                If Data.IndexOf("<EOF>") > -1 Then
                    Dim pszOut As String = Nothing
                    Try
                        Call ProcessCommand(Data, pszOut)
                        lSocket.Send(Encoding.ASCII.GetBytes(pszOut),
             Encoding.ASCII.GetBytes(pszOut).Length, SocketFlags.None)
                    Catch ex As Exception
                        'clean up
                        lSocket.Shutdown(SocketShutdown.Both)
                        lSocket.Close()
                        lSocket = Nothing
                        Return
                    End Try
                End If

                Exit While
            End If
        End While
    Catch ex As Exception
        lSocket = Nothing
    Finally
        'clean up
        Try
            lSocket.Shutdown(SocketShutdown.Both)
            lSocket.Close()
            lSocket = Nothing
        Catch ex As Exception
            lSocket = Nothing
        Finally
            lSocket = Nothing
        End Try
    End Try
End Sub

					  

The method shown in the preceding listing will be created as a temporary thread by our <StartListener> method, which will listen for incoming connections and then create a temporary thread to process the request. The temporary thread accepts a socket as a parameter.

Next, we call the <ProcessCommand> method, just as we did earlier, and then send the response to the caller. Last, we close the socket and consider the communication closed. Although this requires us to continually recreate new sockets for the same client calling many different methods, or calling the same method many times, it is for demonstration purposes only. We are not required to drop this socket at all. We could simply make the temporary thread go back into a receive blocking state waiting for a new command from the client.

We could also consider using asynchronous sockets instead of synchronous sockets; however, depending on the workload required, synchronous sockets work for a fast, small service that has limited functional requirements and connections.

Updating the <StartListener> Method

We need to update our primary thread method because we only want it to listen for incoming connections now and not process them. Let’s review the new code, shown in Listing 2.

Listing 2. The new <StartListener> method.
Private Sub StartListener()
    While Not m_ThreadAction.StopThread
        If Not m_ThreadAction.Pause Then
            Try
                Dim localEndPoint As IPEndPoint = Nothing

                m_Listener = New Socket(AddressFamily.InterNetwork, _
                              SocketType.Stream, ProtocolType.Tcp)

                Dim ipHostInfo As IPHostEntry =
                               Dns.GetHostEntry(Dns.GetHostName())
                Dim ipAddress As IPAddress = ipHostInfo.AddressList(0)

                localEndPoint = New IPEndPoint(ipAddress.Any, Me.Port)

                m_Listener.Bind(localEndPoint)
                m_Listener.Listen(Me.MaxConnections)

                While Not m_ThreadAction.StopThread
                    Dim tmpSocket As Socket
                    tmpSocket = m_Listener.Accept

                    Dim tmpThread As New Thread(AddressOf SocketThread)
                    tmpThread.IsBackground = True
                    tmpThread.Name = "Socket Thread"
                    tmpThread.Start(tmpSocket)
                End While
            Catch nex As SocketException
                WriteLogEvent(My.Resources.ThreadErrorMessage + "_" +
                      nex.ToString + "_" + Now.ToString, THREAD_ERROR,
                      EventLogEntryType.Error, My.Resources.Source)
            Catch tab As ThreadAbortException
                WriteLogEvent(My.Resources.ThreadAbortMessage + "_" +
                      tab.ToString + "_" + Now.ToString, THREAD_ABORT_ERROR,
                      EventLogEntryType.Error, My.Resources.Source)
            Catch ex As Exception
                WriteLogEvent(My.Resources.ThreadErrorMessage + "_" +
                      ex.ToString + "_" + Now.ToString, THREAD_ERROR,
                      EventLogEntryType.Error, My.Resources.Source)
            End Try
        End If

        If Not m_ThreadAction.StopThread Then
            Thread.Sleep(THREAD_WAIT)
        End If
    End While
End Sub

					  

Now that we have our processing thread, this code just needs to wait for an incoming socket connection and then hand that socket off to our processing thread. It simply creates a local background thread and then passes it the socket that it just accepted from the client. Notice that our error handling is not as exhaustive as it could or should be. You should be very careful when deciding to run any type of service, especially when it comes to error handling and resources.

Service Validation

Install the new service and make sure that your configuration file has at least two separate entries for ports to listen on, with more than a single connection as its MaxConnections property.

Run multiple instances of the test client, assigning different ports to the test client to cover all possible listening server ports you configured. For each client you should receive a response from the server on the specified port. You can even run multiple instances of the client against the same port and each client will still receive its own response. Remember that the accept method can only accept one socket connection at a time per server port, so you won’t be able to receive a response at the same instant that you do on another—the server has to process the incoming connection and hand it off to the processing thread. Also, remember that your MaxConnections property specifies how many connections can wait in the backlog of queued requests to the server. So if you launch, for example, 11 or more clients and expect them all to work at the same time, you’ll be disappointed. When more than 10 clients are queued, client connections will start to fail.

Other  
  •  Microsoft Visual Basic 2008 : Services That Listen - Listening with TCP/IP
  •  Seagate GoFlex Satellite Wireless
  •  Toshiba MQ01ABD100 1TB Hard Drive
  •  View Quest Retro WI-FI Radio
  •  Microsoft Enterprise Library : Non-Formatted Trace Listeners (part 3) - Adding Additional Context Information, Tracing and Correlating Activities
  •  Microsoft Enterprise Library : Non-Formatted Trace Listeners (part 2) - Logging to a Database, Testing Logging Filter Status
  •  Microsoft Enterprise Library : Non-Formatted Trace Listeners (part 1) - Creating and Using Logentry Objects, Capturing Unprocessed Events and Logging Errors
  •  Introducing Windows Presentation Foundation and XAML : Transforming Markup into a .NET Assembly
  •  Introducing Windows Presentation Foundation and XAML : Building a WPF Application using Only XAML
  •  Intel : We For One Welcome Our Apple Overlords
  •  
    Top 10
    - Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 2) - Wireframes,Legends
    - Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 1) - Swimlanes
    - Microsoft Visio 2013 : Adding Structure to Your Diagrams - Formatting and sizing lists
    - Microsoft Visio 2013 : Adding Structure to Your Diagrams - Adding shapes to lists
    - Microsoft Visio 2013 : Adding Structure to Your Diagrams - Sizing containers
    - Microsoft Access 2010 : Control Properties and Why to Use Them (part 3) - The Other Properties of a Control
    - Microsoft Access 2010 : Control Properties and Why to Use Them (part 2) - The Data Properties of a Control
    - Microsoft Access 2010 : Control Properties and Why to Use Them (part 1) - The Format Properties of a Control
    - Microsoft Access 2010 : Form Properties and Why Should You Use Them - Working with the Properties Window
    - Microsoft Visio 2013 : Using the Organization Chart Wizard with new data
    REVIEW
    - First look: Apple Watch

    - 3 Tips for Maintaining Your Cell Phone Battery (part 1)

    - 3 Tips for Maintaining Your Cell Phone Battery (part 2)
    programming4us programming4us
    programming4us
     
     
    programming4us