Fun with TCP/IP Sockets
August 23, 2005
by Steve Hagenlock
Sockets in Director
The relationship between Director and TCP/IP has extended far back to the early days, when an XCMD from the Hypercard world allowed for the creation of some simple sockets. When Macromedia released the Multiuser XTRA and Server combination, many doors were opened including the ability for the Multiuser XTRA to open connecting, text-based sockets with several types of socket servers, provided that they didn’t implement binary protocols. We’ve often used the Multiuser XTRA in the quest to allow Director to converse with the outside world, but clearly there are limitations to what can be done with the Macromedia networking solutions including the fact that the Multiuser XTRA has been put to rest as far as development is concerned and neither it, nor the Flash XML Socket can create listening socket servers for general use. (The MU XTRA can create a listening socket as long as the Multiuser protocol is used.) Fortunately, there are options available if you need to do more than the Multiuser XTRA or a Flash XML Socket can accomplish.
Third-party solutions
In the solution that we’ll be discussing, we put to use two products which work in combination to extend and enable Director to work with a library for creating and managing Winsock sockets.
The WinsockQ ActiveX Component for Sockets, is provided by Datawizard (http://www.datawizard.net). This product is primarily aimed at consumers of ActiveX and COM automation technology, such as Visual Basic developers at a cost of $199.00. It is necessary that each computer which will use an ActiveX control have that control registered with the Windows OS. Usually, the act of registering an ActiveX control with the OS is the job of your installation program that you create for your product, or in the case of developer installations, that is handled for you during the install. This is surely not the only solution available for manipulating sockets using ActiveX, however I’ve found it to work well for my needs.
To interface with this socket library, we employ the VBScript XTRA from Xtramania (http://www.xtramania.com). The VBScript XTRA licensing has an option for use with a single control and costs $75.00 in this configuration. The VBScript XTRA allows for the implementation of a diverse set of products from the world of ActiveX/COM automation. Many different solutions can be assembled with the help of this product. Some of the uses of the networking technique that we are discussing require the ability to deal with data in a binary form. The VBScript XTRA provides this functionality in the form of a Binary Wrapper, which handles translation and storage of Lingo variables into a Binary Wrapper instance.
Anatomy of a simple echo server
A simple, “Hello World” style program can be created for testing this technique. Let’s dissect a Parent Script which creates a simple echo server. An echo server will echo back anything that it receives. Thus, if you create a telnet session with a socket with an echo server running behind it, you’ll see what you type being echoed back to your telnet session’s output.
The socket creation process works like this:
- Create and configure your socket object using the VBScript XTRA. This takes place in the NEW handler of the Parent Script. Here we are dealing with the port, socket type, Ethernet adapter, and the connection request buffer.
- The actual socket creation takes place in the mInit() method. Notice that we are using the VBScript method – createObject(). This method creates a COM automation object of the given name and returns an instance of the COM object from which we’ll be controlling.
- Once the Automation Object has been created, we then invoke WinsockQ’s Activate() method, then use its addListener() method to configure and create our listening socket. The WinsockQ automation object, pSocketLib, is now capable of storing multiple socket manager instances.
- Lastly, we need to provide a landing point for the callbacks that will be issued by pSocketLib when it receives events such as connection requests, disconnection notices and data received events. We do this by assigning our ME reference to the EventsHandler property of pSocketLib.
At this point, we have a functioning listening socket server up and waiting for connections on port 1700. The working Lingo code for this Parent Script is below:
property pSocketLib -- <object> VBScript Object
property pSocket -- <object> Socket Instance
property pSocketConnections -- <Prop List> for storing active sockets
property pPort -- <Integer> Port number
property pProtocol -- <Symbol> TCP or UDP Socket type
property vb -- <object> VBScript XTRA base instance
on new me
pPort = 1700
pProtocol = #tcp
--Number of Backlogged connection requests which can sit in Queue.
lBacklog = 10
--Default Ethernet adapter, assumes a single adapter system
lAdapter = - 1
--Create the Socket Manager
me .mInit(pProtocol,lAdapter,lBacklog, pPort)
--Assign this parent script as the event handler for callbacks.
pSocketLib.EventsHandler = me
--[integer sock_handle:[integer sock_handle, boolean accept]]
pSocketConnections = [:]
return me
end
--
--Socket creation
on mInit me, lProtocol, lAdapter, lBacklog, pPort
vb = xtra ( "vbScriptXtra")
pSocketLib = vb.createObject( "WinsockQ.cWinsockQ")
pSocketLib.Activate( TRUE)
pSocket = pSocketLib.AddListener(pPort, lProtocol, lAdapter, lBacklog)
end
--
-- Shutdown method
on mDestroy me
pSocketLib.CloseSock(pSocket)
pSocketLib.Activate( FALSE)
pSocketLib = 0
end
----------Methods, these are wrapper methods for the ActiveX component
-- Send data to all connected sockets, each socket instance is stored
-- in the pSocketConnections property list
on SendData me, lData
repeat with sock in pSocketConnections
so = sock.SocketHandle
pSocketLib.SendData(so, lData)
end repeat
end
----------Events, these are all callbacks from the ActiveX Component
-- Called upon a request for connection
on ConnectionRequest me, args
--args : [#SocketHandle:Integer socket handle,
-- #Accept: Boolean accept]
-- NOTE: Change the #Accept value to FALSE to refuse the connection.
lSock = args
pSocketConnections. addProp(args.SocketHandle,args)
return args
end
-- Called when a socket is closed.
on ConnectionTerminated me, args
pSocketConnections. deleteProp(args.SocketHandle)
end
-- Called when data has arrived, process it according to the rules of
-- an echo server, which is send that data back to the client.
on DataArrival me, args
--args : [#SocketHandle:Integer socket handle,
--#data:#obj-VBScriptXtra Instance Binary Data,
--#retrieved:Integer - Retrieved char count]
--Echo data back to all connections
me .SendData(args.data. String)
end
This Parent Script implements the following:
- Socket Creation and Destroy methods.
- A method for writing data to a socket.
- Callback landing points for Connection Requests, Termination notices, and Data Arrival events.
- A wrapper method for sending data to all socket instances stored in the pSocketConnections list.
To see the results of this script working, you could instantiate the parent script then open a DOS command line and use Telnet to connect to the socket
C:\Telnet 127.0.0.1 1700
If you type into the Telnet window, you will see what you type, this occurs because the socket object is echoing what you typed back to you.
Real-world Solutions
The echo server we created is neat, but not very useful, let’s take a look at some things that you can do using this technique.
- Non-interactive Message Window. A simple, non-interactive server which provides ‘Message Window’ functionality by overriding the lingo PUT command to send its output to a socket manager instance. Essentially, you can ‘Telnet into Director’ and watch the streaming outputs of your PUT commands. Let’s say that you have a collection of machines testing your Director software, you can create a telnet session with each machine and watch what you’ve deemed important enough to dump to the message window.
- Flash XML Socket Server. Create a Flash-compatible XML Socket server. Have you ever wanted to control or converse with a Director Projector using an external Flash movie? You can do it with this. The Flash XML Socket is not limited to sending/receiving XML formatted data, you can send ASCII data of any form as long as the messages are delimited by a NULL byte. This technique allows you to create a Peer-to-Peer connection similar to what you would do with two Projectors connecting to each other using the Multiuser XTRA and conversing in the Multiuser Protocol. Normally, to get Director and Flash conversing, you would need an XML Socket Server and use an embedded Flash movie in Director implementing the communications.
- Proxy communications through an Application Server. You can implement secure control connections for remote, firewalled machines in conjunction with a web application server environment such as Apache/PHP. In this scenario, your commands would be sent to Apache as http/https GET or POST transactions and use the PHP scripting language to create the socket with the Projector running on the machine, transfer the data payload through the socket, receive any data that the Projector may respond with,. close the socket and finally return that data to the remote requester. In this scenario, you can implement your security policies in the Apache/PHP layer, which provides a rich set of authentication and encryption functionality.
Conclusion
For certain types of applications, industrial strength, standards-based communication tools are helpful, and often necessary. Vanilla Director projects have not had the ability to play the role of a tcp/ip socket server without caveats and limitations. Using techniques such as these allows for a wider range of functionality available to developers of Windows projects by taking advantage of the multitude of software available in the ActiveX/COM market and harnessing their power through the application of the VBScript XTRA.
Copyright 1997-2024, Director Online. Article content copyright by respective authors.