Day 040 - Socket communication

Page 382 of the tutorial introduces socket programming. 

As the tutorial explains, a socket "is a communication resource used by the applications to communicate between computers regardless of the network type". 

Essentially, with sockets you can set up your own network communication channels to manage private communication between your applications or to connect to outside servers or clients. 

The "WD using sockets" example shows one way to manage client/server communication. If you run the executable (which I suggest you do via Windows Explorer or a command prompt, as you'll need to run more than one copy) you'll see this window:

I started off with a server, and got this:

I then launched another instance and ran it as a client:

and got this window:

I launched two more clients, each one with a different value in the Login field, and started sending some messages around:

Note that the server apps now lists three clients (all on the same local IP address). Any message sent from one of the clients goes to the server and is then broadcast back to all clients. 

Here's the code the server uses to begin listening:

PROCEDURE ListenConnections()
sChannelName is string
sThreadName is string
// Wait for connections
LOOP	
	Multitask(-2)
	
	IF SocketWaitForConnection(csNameListeningSocket) THEN
		
		// New request for connection
		// Accept the connections
		sChannelName = SocketAccept(csNameListeningSocket)
		
		// Check the acceptance operation
		IF sChannelName~="" THEN
			Error("Unable to create the socket for the new connection",ErrorInfo())
			BREAK
		ELSE
			// Start a thread to manage this connection
			sThreadName = sChannelName
			ManageConnection(sChannelName)
						
		END
	END	
END

This code is waiting for the following to execute on the client:

Multitask()
// Display the connection settings in the window title bar
MyWindow..Title = gfsLogin+" on the server: "+gfsServer
// Connecting to the server
SocketConnect(csSocketName,cnCntPort,NetIPAddress(gfsServer))
IF ErrorOccurred THEN
	// Error during the connection
	Error("Unable to connect to the server",ErrorInfo())
	Close
END
// Run the thread for incoming messages
Receive()

Both the client and the server use threading to handle the socket communications. The server runs the ManageConnection procedure, which runs on its own thread. This code is a loop that listens for incoming messages which can be a command ("BYE") or a message which gets rebroadcast via the ManageMessage procedure. 

PROCEDURE ManageConnection(sConnectionName)
sMessage is string
sIp is string = SocketClientInfo(sConnectionName,SocketAddress)
// Read the messages
LOOP
	
	IF EventWait("TERM",5) THEN BREAK
	
	UpdateTable(sConnectionName,sIp)
	sMessage = SocketRead(sConnectionName,False,10)
	
	SWITCH sMessage
		CASE "BYE" :
			// User exit
			BREAK
			
		CASE "" :
			// Non-locking read operation, back to the loop
			Multitask(-1)
						
		OTHER CASE :
			// Message to post			
			ManageMessage(sMessage)			
	END
END
// Closing the socket
SocketClose(sConnectionName)

ManageMessage simply loops through its list of connections and sends out the message:

PROCEDURE ManageMessage(sMessage)
CriticalSectionStart("Management")
sSocketName is string
// Send the message to all connected users
FOR ALL ROW OF Table1
	
	// Retrieve the name of the socket
	sSocketName = Socket
	
	// Check the existence of this socket 
	IF SocketExist(sSocketName) THEN		
		// Send the message
		SocketWrite(sSocketName,sMessage)	
	END
END
CriticalSectionEnd("Management")

Back on the client side, the Receive procedure (which is also running on a thread) sits and waits for incoming messages, displaying them as they arrive. 

PROCEDURE Receive()
sMessage is string
// Wait for messages as long as the thread is not stopped
LOOP
	// Wait and read the next message
	WHEN EXCEPTION IN
		sMessage = SocketRead(csSocketName,False,20)
	DO
		Error("Problem with inbound socket",ExceptionInfo())
		BREAK
	END
	
	IF NoSpace(sMessage)<>"" THEN
		// Add the message to the end of table
		TableAddLine(Table1,sMessage)
	END	

	Multitask(-2)
END

There's more code, but that's the heart of what's going on in the sockets example. 

I'm assuming the underlying protocol is TCP, since there's a separate way to create UDP sockets in WinDev. TCP and UDP are two of the most common transport protocols, and are lower level than application protocols such as HTTP, SMTP, FTP etc. So this is a pretty low level way of communicating between applications/devices. WinDev does have built in support for some of the higher level protocols (such as email and FTP) so it's not like you have roll your own protocols in all situations.

When communicating between two WinDev apps, it's recommended that you use the WinDev standard for determining message size, which is to begin with the size of the message, followed by <CR>, followed by the message. You can also use a delimiting character - see the help on SocketChangeTransmissionMode for more.

Besides TCP and UDP support, there are socket functions for establishing SSL, infrared and Bluetooth connections. See the socket functions page.

The tutorial itself has very little to say about how socket communications work, but the example is well worth a look.