Library tutorials & articles

A TCP/IP socket server object for Visual Basic

An example server in VB

As a simple example we will develop an echo server that stores some per-connection state and can optionally shut down the connection in a variety of ways after echoing a certain number of data packets.

Our echo server consists of two forms. The first allows you to specify the port that the server should listen on and also set some parameters. When a server is created the second form is displayed, this contains a list control and handles the events that the server fires. After creating a server you can switch back to the first form, change the port number and create another server. All servers can operate independently.

The code behind the first form is fairly simple and mostly consists of managing the user interface elements and passing parameters to the second form. The work required to create the socket server itself is very simple.

Option Explicit

Private Sub Command1_Click()

   Dim server As JBSOCKETSERVERLib.server
   Set server = CreateSocketServer(CLng(Text1.Text))
   
   Dim frm As Form2
   Set frm = New Form2
   
   frm.SetServer server
   frm.ShowDataPackets.Value = ShowDataPackets.Value
   frm.DataIsBytes.Value = DataIsBytes.Value
   frm.DataIsString.Value = DataIsString.Value
   frm.SignOnAsUnicode.Value = SignOnAsUnicode.Value
   
   If ShutdownEnabled.Value Then
   
       If ShutdownSocket.Value Then
           frm.ShutdownAfter = CLng(ShutdownAfter.Text)
       ElseIf CloseSocket.Value Then
           frm.CloseAfter = CLng(ShutdownAfter.Text)
       End If
   
   End If
   
   server.StartListening
   
   frm.Show , Me

End Sub

Private Sub ShowDataPackets_Click()

   DataIsFrame.Enabled = ShowDataPackets.Value
   DataIsBytes.Enabled = ShowDataPackets.Value
   DataIsString.Enabled = ShowDataPackets.Value

End Sub

Private Sub ShutdownEnabled_Click()

   ShutdownSocket.Enabled = ShutdownEnabled.Value
   CloseSocket.Enabled = ShutdownEnabled.Value
   ShutdownAfter.Enabled = ShutdownEnabled.Value
   
End Sub

The second form is slightly more complex. The code that handles the socket server is as follows:

Option Explicit

Dim WithEvents m_server As JBSOCKETSERVERLib.server
Public ShutdownAfter As Integer
Public CloseAfter As Integer

Private ListWidth As Integer
Private ListHeight As Integer

Public Sub SetServer(server As JBSOCKETSERVERLib.server)

   Set m_server = server
   
   Caption = "Socket server listening on: " & server.LocalAddress.Port
   
End Sub

Private Sub m_server_OnConnectionClosed(ByVal Socket As JBSOCKETSERVERLib.ISocket)

   If ShowDataPackets.Value Then
       AddToList "OnConnectionClosed : " & GetAddressAsString(Socket)
   End If
   
   Dim counter As Class1
   Set counter = Socket.UserData

   If ShowDataPackets.Value Then
       AddToList "User data = " & counter.GetCount()
   End If
   
   Socket.UserData = 0

End Sub

Private Sub m_server_OnConnectionEstablished(ByVal Socket As JBSOCKETSERVERLib.ISocket)

   If ShowDataPackets.Value Then
       AddToList "OnConnectionEstablished : " & GetAddressAsString(Socket)
   End If
   
   Dim counter As Class1
   Set counter = New Class1
   
   Socket.UserData = counter
   
   Socket.WriteString "Welcome to VB echo server" & vbCrLf, SignOnAsUnicode.Value

   Socket.RequestRead

End Sub

Private Sub m_server_OnDataReceived( _
   ByVal Socket As JBSOCKETSERVERLib.ISocket, _
   ByVal Data As JBSOCKETSERVERLib.IData)

   Dim counter As Class1
   Set counter = Socket.UserData
   
   counter.IncrementCount

   If DataIsBytes.Value Then
   
       OnReceivedBytes Socket, Data, counter.GetCount
   
   ElseIf DataIsString.Value Then
   
       OnReceivedString Socket, Data, counter.GetCount

   End If

   Socket.RequestRead

   If ShutdownAfter <> 0 And ShutdownAfter = counter.GetCount Then
       Socket.Shutdown ShutdownBoth
   End If
   
   If CloseAfter <> 0 And CloseAfter = counter.GetCount Then
       Socket.Close
   End If

End Sub

Private Sub OnReceivedBytes( _
   ByVal Socket As JBSOCKETSERVERLib.ISocket, _
   ByVal Data As JBSOCKETSERVERLib.IData, _
   counter As Integer)

   Dim Bytes() As Byte
   Bytes = Data.Read()

   If ShowDataPackets.Value Then
   
       Dim stringRep As String
       
       Dim i As Integer

       For i = LBound(Bytes) To UBound(Bytes)

           stringRep = stringRep & CLng(Bytes(i)) & " "

       Next i
   
       AddToList "OnDataReceived : " & GetAddressAsString(Socket) & " - " & stringRep
   
   End If
       
   Socket.Write Bytes

End Sub

Private Sub OnReceivedString( _
   ByVal Socket As JBSOCKETSERVERLib.ISocket, _
   ByVal Data As JBSOCKETSERVERLib.IData, _
   counter As Integer)

   Dim theData As String
   theData = Data.ReadString
   
   If ShowDataPackets.Value Then
       AddToList "OnDataReceived : " & GetAddressAsString(Socket) & " - " & theData
   End If
         
   Socket.WriteString theData, False
   
End Sub

Private Function GetAddressAsString(Socket As JBSOCKETSERVERLib.ISocket) As String

   GetAddressAsString = Socket.RemoteAddress.Address & " : " & Socket.RemoteAddress.Port

End Function

The code is made more complex by the fact that we can display and echo the data and shut down the connection in all of the possible ways. Notice how we initialise our user data in the m_server_OnConnectionEstablished event and store it in the Socket. We then retrieve and use it in the m_server_OnDataReceived and m_server_OnConnectionClosed events.

Comments

  1. 11 May 2006 at 16:46

    I ran the server on one machine and the client on another and managed to get a connection and send some data. However after sending a few test messages "1234567890" I try and receive as string at the other end and it stops working. I put in extra calls in the event handlers and they don't get called. The sender thingks it has sent the data. The only way I can stop it is to open the connection again and then press send. Any ideas?

    Also when I close down the server, Windows2000 server won't let me delete the file even though it is not in the process list - is there some resource that needs closing in the code somewhere on exit?

    I am trying to get a reliable point to point comms for sending some string data.

    Ross D.







  2. 18 Sep 2005 at 22:25

    There was a stupid precedence error in the original code, this may be related to it?


    LPOLESTR pOle = ((lpa = (char*)mpData) == NULL) ? NULL : ATLA2WHELPER((LPWSTR) alloca(mlength + 1*2), _lpa, mlength);


    should be


    LPOLESTR pOle = ((lpa = (char*)mpData) == NULL) ? NULL : ATLA2WHELPER((LPWSTR) alloca((mlength + 1)*2), _lpa, mlength);

  3. 18 Sep 2005 at 22:22

    I'm afraid I don't have a free version of this code that includes client support.

  4. 18 Sep 2005 at 22:17

    Yes.

  5. 19 May 2004 at 15:09

    may I use this library for a client application? do you have another dll to do this (with vb6)? great job

  6. 18 May 2004 at 17:45
    the function Data.ReadString is not working - any idea? (Data.Read is working normally...) if you type in a terminal it's ok, but if you do a batch the routine stops...
  7. 13 Feb 2004 at 13:32

    There're several useful Winsock tutorial on this site... But its not detailing enough considerations in helping newbie extend the tutorial into actual application environment.  One of them is providing a tutorial on preventing reentrancy when working high socket traffic scenario.


    Typical Winsock application logic when data arrives...


    1.  The Winsock_DataArrival event fires when client sockets send data to the listening socket server
    2.  On Data Arrival, Inspect the data received
    3.  Process the data received (e.g.  Lookup Databases, Refresh GUI, and others)


    When multiple data stream or even large chunk of data arrive while your code is Processing "time-instensive" routines/tasks will require u to implement a FIFO buffer into your code to ensure all incoming data are captured and processed properly...  I'm pleading for the community to add this logic to existing tutorial or post some sample code.  Thanks in advance.

  8. 28 Oct 2003 at 04:38

    Does you server support multiple clients connecting simultaneously?

  9. 01 Jan 1999 at 00:00

    This thread is for discussions of A TCP/IP socket server object for Visual Basic.

Leave a comment

Sign in or Join us (it's free).

Len Holgate Len has been programming for over 20 years, having first started with a Sinclair ZX-80. Now he runs his own consulting company, JetByte Limited. JetByte provides contract programming and consultanc...
AddThis

Related podcasts

  • Java Posse #206 - Newscast for Sept 17th 2008

    Newscast for Sept 17th 2008Fully formatted shownotes can always be found at http://javaposse.com Java complexity again, but from a different angle:http://forums.java.net/jive/thread.jspa?messageID=298125&tstart=0#298125 JVM Language summit - the details emergehttp://openjdk.java.net/project...

Want to stay in touch with what's going on? Follow us on twitter!