revUp - Updates and news for the LiveCode community
Issue 156 | october 18th 2013 Contact the Editor | How to Contribute

Using Sockets
This lesson shows you how to use sockets and create a simple broadcast server

Introduction

Sockets provide the programmer with a facility to allow their applications to communicate over a network. This lesson shows how to use sockets to allow to LiveCode apps to talk to each other.

What are Sockets?

Sockets provide two networked machines with a bidirectional communication channel. One machine will be the server, listening in for connections and the other, the client, attempting to make a connection with the server. An example of this would be when you fetch a web page. Your web browser, or the client, attempts to make a connection to the web server. The web server, listening in for clients, will accept the connection and then proceed to handle the clients request. Here, the browser will ask the web server for the page, before the web server responds with the page data.

Servers are accessed via socket addresses, a combination of the server's IP address (or domain name) and a port number. The port can be thought as a connection point on the sever, like USB or Firewire ports, with each port serving a specific purpose. For example, web pages are served on port 80 (HTTP) , emails are sent via port 25 (SMTP).

Once two machines are connected, they can then communicate streams of bytes with each other. It's up to the client and server to format these byte streams into structured data chunks. A simple example would be an echo sever, which receives a stream of bytes from a client, assumes they form an ascii string and sends the string back to the client.

As noted previously, sockets use IP based networks. There are a range of transport layers that can be used on top of IP. In this lesson we will consider TCP sockets.

How to Use Sockets in LiveCode - Server Side

Using sockets in LiveCode is very simple. First of all let us consider a server: A server must listen in on a specific port for clients. To do this in LiveCode, we simply use the following command:

accept connections on port 1234 with message "clientConnected"

Here, our server will listen in on port 1234 for connecting clients. When a client is connected, the message "clientConnected" will be sent, detailing the newly opened socket. The server can now listen in on this socket for messages from the client:

on clientConnected pSocket
read from socket pSocket with message "messageReceived"
end clientConnected

In the example above, the server is reading from the client in non-blocking mode. That means that the read request will exit instantly. When a data is received from the client, the "messageReceived" message will be sent, detailing the socket it came from and the data sent. The alternative to this is to omit the "with message". Here the read will function in blocking mode, not returning until data has been received from the client. When data is received, the read command will return and the data will be placed in it.

An additional parameter can be passed to the read command, detailing how much data we want to read. This can be a number of characters or lines (or any other chunk type - read from socket pSocket for 5 lines) or until a specific character is reached (read from socket pSocket until return).

Let us consider the read as detailed earlier, in non-blocking mode. When data is received from the client the "messageReceived" message will be sent. At this point, the server can choose to write a response to the client. Here, we will just echo the data back to the client using the write command.

on messageReceived pSocket, pMsg
write pMsg to socket pSocket
read from socket pSocket with message "messageReceived"
end messageReceived

Like the read command, write can be blocking or non-blocking. If we want a non blocking write, we simply specify the message to be sent when the write is complete. Note that in order to continue reading from the client, we must issue another read command.

When the server no longer wishes to communicate with the client, the socket can simply be closed with the command close socket tSocket. If the client closes the socket, the server will be sent a socketClosed message, detailing the socket that has been closed.

How to User Sockets in LiveCode - Client Side

Using sockets on the client side is equally as easy in LiveCode. To begin communicating with the server, we must first open a socket:

open socket to "host:port" with message "clientConnected"

Like the read and write commands, the callback message on the open command is optional, and defines if the command is blocking or non-blocking. If used in blocking mode, once connected the newly opened socket will be accessible via the it variable. In non-blocking mode, it will be passed as a parameter in the callback message.

If there has been an error connecting to the server the "socketError" message will be sent. (If the error is due to a problem finding the specified host, the error message is returned in the result, and no "socketError" message is sent.)

Let us consider the open command in non-blocking mode. Once the socket is opened, we can write a message to the server, read the response and then close the connection:

on clientConnected pSocket
write "hello" & return to socket pSocket
read from socket sSocket until return
put it
close socket pSocket
end clientConnected

The read and write commands function in exactly the same manner as defined previously for the server.

Creating a Simple Broadcast Server

Let us expand on these commands and create a simple broadcast server. Our broadcast server will listen in for connecting clients. Once a client is connected, the server will place the client on its list of connected clients before attempting to read a line of data from it. When a line of data is read from a client, that data will be broadcast to each connected client.

The list of connected clients will simply be a script variable holding the socket for each client separated by return. Our server will be started and stopped using simple start and stop commands. Two further handlers will be defined: One called when a client is connected, adding the client to the list before beginning reading. The other will be called when the read is complete, broadcasting the read message to all connected clients.

local sConnectedClients -- list of authorised clients
local sRunning -- if the server is currently running

constant kPort = 8010

-- Start the server listening for connections. When a client attempts to
-- connect, the broadcastServerClientConnected message will be sent.
command broadcastServerStart
if not sRunning then
put true into sRunning
accept connections on port kPort \
with message "broadcastServerClientConnected"
end if
end broadcastServerStart

-- Stop the server listening for connections. Close all open communication
-- channels.
command broadcastServerStop
if sRunning then
put false into sRunning
put empty into sConnectedClients
repeat for each line tSocket in the opensockets
close socket tSocket
end repeat
end if
end broadcastServerStop

-- Sent when a client attempts to make a connection. Store the client
-- in the connected list and begin reading lines of text from them. The
-- broadcastServerMessageReceived message will be sent when a line is received.
on broadcastServerClientConnected pSocket
put pSocket & return after sConnectedClients
read from socket pSocket until return \
with message "broadcastServerMessageReceived"
end broadcastServerClientConnected

-- Sent when a line of text is read from a client. Broadcast that line of
-- text to all connected clients.
on broadcastServerMessageReceived pSocket, pMsg
repeat for each line tSocket in sConnectedClients
write pMsg to socket tSocket
end repeat
read from socket pSocket until return \
with message "broadcastServerMessageReceived"
end broadcastServerMessageReceived

-- Sent when a client disconnects. Remove the client from connected list
on socketClosed pSocket
delete line lineoffset(pSocket, sConnectedClients) of sConnectedCLients
end socketClosed

Creating a Broadcast Client

Now lets define our client. This is really easy. We just, as before, connected to the server. Once connected, we can begin sending messages by calling the "sendMessage" handler. This handler will simply write the message to the server using the socket we connected with.

The other task of the client is to listen for any messages broadcast by the server. Here, the client will just read from the server in non-blocking mode, logging the message read before continuing the read.

local sSocket
constant kPort = 8010

-- Connect the client to the given server. Will send a broadcastClientConnected
-- when the client has connected.
command broadcastClientStart pServer
if sSocket is empty then
open socket to pServer & ":" & kPort \
with message "broadcastClientConnected"
end if
end broadcastClientStart

-- Disconnect the client from the broadcast server.
command broadcastClientStop
if sSocket is not empty then
close socket sSocket
put empty into sSocket
end if
end broadcastClientStop

-- Write the given message to the communication channel the client
-- has opended with the broadcast server.
command broadcastClientSend pMsg
if sSocket is not empty then
write pMsg & return to socket sSocket
end if
end broadcastClientSend

-- Sent once the client has connected to the broadcaset server.
-- Store the socket for futurure reference and begin reading data
-- from the server.
on broadcastClientConnected pSocket
put pSocket into sSocket
read from socket sSocket until return \
with message "broadcaseClientMessageReceived"
end broadcastClientConnected

-- Sent when a message has been received from the server. Output the
-- message and continue reading data from the server.
on broadcaseClientMessageReceived pSocket, pMsg
put pMsg after field "log"
read from socket sSocket until return \
with message "broadcaseClientMessageReceived"
end broadcaseClientMessageReceived

-- Sent when there is an error opening the socket. Log the error.
-- and close the socket.
on socketError pSocket, pError
broadcastClientDisconnect
put pError & return after field "log"
end socketError

-- Sent when the connection to the server is closed by the server.
on socketClosed
put empty into sSocket
end socketClosed

The image above shows our broadcast client communicating with the server and another client connected via telnet.

In the next edition we'll look at creating a communication protocol and a LiveCode Chat Server.

 

Main Menu

What's New


Get App2Market Today