Echo Server Example The next step is to implement your own echo server. The server will listen on the echo port, accept connections from one or more clients and echo back any data that is sent to it. First, start a new Visual Basic project with a single form, a button in the center of the form and the SocketWrench control. It might look something like this: The first that we need to do is create a global variable called LastSocket which we will use to keep track of the number of clients that have connected to our server. This should be done in the general declaration section, as follows: Dim LastSocket As Integer Next, we will initialize the form in the Load subroutine with the following code: Private Sub Form_Load() Command1.Caption = "Listen" LastSocket = 0 End Sub When the user presses the command button, we want the server to begin listening for connections. Remember that the first thing that a server application must do is listen on a local port for incoming connections from a client. You'll know that a client is attempting to connect with you when the OnAccept event is generated for the SocketWrench control. To accept the connection, your program calls the Accept method, passing the listening socket handle as a parameter. As you'll recall from the TCP/IP tutorial, the act of accepting a connection causes a second socket to be created. The original listening socket continues to listen for more connections, while the second socket can be used to communicate with the client that connected to you. If you use the Accept method to accept the connection on the same instance of the control, you're effectively telling the control to close the original listening socket and from that point on the control can be used to communicate with the client. While this is convenient, it is also limiting -- since the listening socket has been closed, no more clients can connect with your program, effectively limiting it to a single client connection. A better approach is to create an additional instance of the control and have it accept the connection, leaving the original listening socket available so that more clients can establish a connection with your server. The problem is, how many clients are going to attempt to connect to you? Of course, you could drop a fixed number of SocketWrench controls on your form, thereby limiting the number of connections, but that's not a very good design. The better approach is to create a control array which can be dynamically loaded when a connection is attempted by a client, and unloaded when the connection is closed. This is the approach that we'll take in our echo server. In order to implement a dynamically-loaded control array, set the Index property of SocketWrench1 to 0. This will also cause VB to include the parameter Index in events that you implement. To have the server begin listening when the button is pressed, we need to add code to the button's Click event. Initially there will only be one instance of the control in our control array, identified as SocketWrench1(0) and it will be used to listen for connections: Private Sub Command1_Click() If Not SocketWrench1(0).Listening Then Dim nError As Long SocketWrench1(0).Blocking = False SocketWrench1(0).Protocol = swProtocolTcp SocketWrench1(0).LocalPort = swPortEcho nError = SocketWrench1(0).Listen() If nError > 0 Then MsgBox "Unable to listen for connections", vbExclamation Exit Sub End If Command1.Caption = "Disconnect" Else SocketWrench1(0).Disconnect Command1.Caption = "Listen" End If End Sub There are two new properties here, the Listening property and the LocalPort property. The Listening property is a boolean flag, similar to the Connected property in our client example. It will return True if the control is currently listening for client connections. The LocalPort property is used by server applications to specify the local port that it's listening on for connections. By specifying the standard port used by echo servers (port 7), any other system can connect to yours and expect the program to echo back whatever is sent to it. If the control is listening for connections and you press the button, it will disconnect the socket. This stops the control from listening for new client connections, however it will not interrupt any clients that have already connected to the server. The reason for this is because the client connections are actually managed on separate sockets which are not affected by closing the listening socket. When our server program is executed and you press the button, the control will begin listening for client connections. When this occurs, the control's OnAccept event will fire. The code for this event should look like this: Private Sub SocketWrench1_OnAccept(Index As Integer, ByVal Handle As Variant) Dim I As Integer For I = 1 To LastSocket If Not SocketWrench1(I).Connected Then Exit For Next I If I > LastSocket Then LastSocket = LastSocket + 1: I = LastSocket Load SocketWrench1(I) End If SocketWrench1(I).Blocking = False SocketWrench1(I).Protocol = swProtocolTcp SocketWrench1(I).Accept Handle End Sub The first thing that we do is iterate through each instance of the control in our control array, checking to see if it is connected to a client. If we find a control that is not connected to a client (in other words, the client has disconnected from the server) then we will re-use that control. If all of the controls are currently being used, then we need to increment the LastSocket variable and dynamically load another instance of the control. Next, we initialize the control's properties, and then the Accept method is called with the Handle parameter that is passed to the control. After executing this statement, the control is now ready to start communicating with the client program. Since it's the job of an echo server to echo back whatever is sent to it, we have to add code to the control's OnRead event, which tells it that the client has sent some data to us: Private Sub SocketWrench1_OnRead(Index As Integer) Dim strBuffer As String Dim cbBuffer As Long cbBuffer = SocketWrench1(Index).Read(strBuffer, 1024) If cbBuffer > 0 Then SocketWrench1(Index).Write strBuffer, cbBuffer End If End Sub Finally, when the client closes the connection, the socket control must also close its end of the connection. This is accomplished by adding a line of code in the control's OnDisconnect event: Private Sub SocketWrench1_OnDisconnect(Index As Integer) SocketWrench1(Index).Disconnect End Sub To make sure that all of the socket connections are closed when the application is terminated, the following code should be included in the form's Unload event: Private Sub Form_Unload(Cancel As Integer) Dim I As Integer If SocketWrench1(0).Listening Then SocketWrench1(0).Disconnect End If For I = 1 To LastSocket If SocketWrench1(I).Connected Then SocketWrench1(I).Disconnect End If Next I End End Sub This will disconnect the listening socket so that no more clients can establish connections, and will then disconnect from each of the clients.