The Socket class allows you to use the low-level networking facilities provided by BSD or Windows sockets, for client-server applications. (See also the GetMail, SendMail and HTTPClient classes, which provide a higher-level interface for mail and HTTP protocols, and which are much easier to use.) It allows your APLX applications to exchange data with other processes, either on the local machine or over a network.
Usually, you will use Socket objects to allow APLX applications to communicate with non-APL processes. You can also use them to allow APLX applications to communicate with each other across a network.
For more details on using sockets, consult any of the standard documents on BSD or Windows socket programming.
Creating and using a socket as a client
The steps you need to carry out at the client end of the connection are as follows:
Creating and using a socket as a server
At the server end of a connection, things are usually a little more complex. This is because a server typically needs to be able to handle multiple client connections simultaneously, and must not get blocked communicating with one client when other clients are also trying to access the service. One way of handling this is to use multiple APLX tasks, with one task per client connection, plus one master task which waits for clients to connect. Another way is to use a single APLX task for everything, and use events to ensure that the task never gets blocked waiting for a response from a client.
The task which is waiting for clients to connect starts up first. It does the following:
Key properties of the Socket object
family: An integer scalar which specifies the address family of the socket. The default is 2, AF_INET, the address family used for the internet. It should be specified before calling the Open or Listen methods.
type: An integer scalar which specifies the socket type. It defaults to 1, SOCK_STREAM. It should be specified before calling the Open or Listen methods.
protocol: An integer scalar which specifies the protocol. It defaults to 0, the default for the address family.
port: An integer scalar which specifes the port number.
timeout: An integer scalar which sets the timeout (in milliseconds) before the Accept or Receive methods will return if no connection request or data is received. A value of
status: Read-only Returns the connection status as a two-element vector. The first element is 1 if the socket is connected, else 0. The second element is the latest error number from the underlying operating-system socket.
handle: An integer scalar, which is the handle of the underlying operating-system handle. You can use this, in conjunction with
Key methods of the Socket object
Open: Open a new connection. (This method should be called from the client end of the connection only.) It takes two arguments. The first is the address of the server (usually an internet domain name or address, or 'localhost' for your own machine). The second is the port number to connect on. The result is a status code indicating whether the connection succeeded: 0 = OK, 1 = Could not find host, 2 = Authentication error, 3 = Other error. (More details of any error are available from the status property).
Listen: Establish the socket as a server listener. This method takes no arguments. (It should be called on the server end of the connection only.). It returns the same error code as Open.
Accept: Wait for a client to try to connect. This method takes no arguments. (It should be called on the server end of the connection only.). It causes the task to block until a connection request is made, or the timeout value is reached. It returns the handle to use for the client connection, or 0 if it timed out or
Receive: Receive some data from the socket. This method takes no arguments. It causes the task to block until data is available, or the timeout value is reached. It returns a character vector which is the data received from the socket, as a raw sequence of bytes with no character translation. It returns an empty vector if it times out or an error occurs.
Send: Send some data to the socket. This method takes as an argument a character vector, which is the raw data to send to the other end of the connection. It returns 0 on success, else 3 if an error occurred.
Close: Disconnect and close the socket. This method takes no arguments. You always ensure the connection is closed cleanly by calling this method when the session is complete.
Callbacks of the Socket object
onConnectRequest: This event occurs on the server end, when you have called Listen and a client tries to connect. It indicates that you should now call the Accept method to accept the connection.
onReceive: This event occurs both on clients and servers. It indicates that the other end has sent some data, which you can now read using the Receive method.
onDisconnect: This event occurs both on clients and servers. It indicates that the other end has closed the connection. You should now call Close, and delete the socket.
∇DEMO_Socket;x;count;handle;cmd;errcode;ServerSock;Client1;Client2;SendSock  ⍝ Show how to use the Socket object. For this demo, we set up a  ⍝ Server and two client APL tasks, all on the local machine  ⍝ using port 10000 (which hopefully won't clash with anything)  Client1←'⎕' ⎕NEW 'APL' ⋄ Client1.wssize←100000 ⋄ Client1.where←0 0 10 20  Client2←'⎕' ⎕NEW 'APL' ⋄ Client2.wssize←100000 ⋄ Client2.where←0 35 10 20  Client1.Open  Client2.Open  ⍝  ⍝ Create sockets in each client APL task  Client1.Execute "MySock←'⎕' ⎕NEW 'Socket'"  Client2.Execute "MySock←'⎕' ⎕NEW 'Socket'"  ⍝  ⍝ Create a socket for the server, in our main task  ServerSock←'⎕' ⎕NEW 'Socket'  ServerSock.port←10000  errcode←ServerSock.Listen  :If errcode≠0  ⍝ Oops, something went wrong  'An error occurred in Listen, error code ',⍕¯1↑ServerSock.status  :Return  :EndIf  ⍝  ⍝ After a few seconds, get the clients to try to connect, and await data  x←⎕DL 3  cmd←"x←MySock.Open 'localhost' 10000 ⋄ 'Server sent: ',MySock.Receive"  Client1.Execute("x←⎕DL 3 ⋄ 'Connecting..' ⋄ ",cmd)  Client2.Execute("x←⎕DL 6 ⋄ 'Connecting..' ⋄ ",cmd)  ⍝  ⍝ Meanwhile, loop round accepting connections  count←0  'Waiting for clients to connect...' ⋄ ⎕CC ' '  :Repeat  handle←ServerSock.Accept  :If handle>0  ⍝ A client is trying to connect  ⍝ Establish new socket to talk to the client.  ⍝ We'll just transfer one packet, then close the connection  'Got connection request.' ⋄ ⎕CC ' '  count←count+1  SendSock←'⎕' ⎕NEW 'Socket'  SendSock.handle←handle  errcode←SendSock.Send('Hello, client task ',⍕count)  SendSock.Close  SendSock.Delete  :ElseIf handle=¯1  ⍝ Oops, something went wrong  'An error occurred in Accept, error code ',⍕¯1↑ServerSock.status  :Leave  :EndIf  :Until count=2  ⍝  ⍝ Wait, then kill the child tasks (this will also delete their sockets)  x←⎕DL 4  Client1.Close ⋄ Client2.Close  ⍝  ⍝ Clean up this end as well  ServerSock.Close ∇
Copyright © 1996-2010 MicroAPL Ltd