Communicating via TCP/IP

Sometimes apps need to communicate with other apps on the same network. This can be accomplished using the SSLSocket or TCPSocket classes. SSLSocket can send and receive data using the TCP/IP Internet protocol, using both secure and non-secure communication. TCPSocket can only do non-secure communication.

Use these socket classes to communicate with other computers on the same network. When you connect to the Internet, you are part of the Internet network. This allows you to communicate with other computers on the Internet via TCP/IP.

Security

The SSLSocket class is used to do secure communications via TCP/IP. It works similarly to the TCPSocket class, but has additional properties for the connection type, managing certificate locations and for checking if a secure connection was made. You are strongly encouraged to use SSLSocket for secure communication.

Set up

To get started with TCP/IP communication, you need to add an SSLSocket class to your project. The easiest way to do this is to drag a TCPSocket control from the Library to the window or the Navigator and then change its Super to SSLSocket.

Before you can connect to another computer using a socket, you must first set the port. The port is to TCP/IP what channels are to television or frequency assignments are to radio stations. Ports give an app the ability to focus on specific data rather than receiving all the data transmitted to your computer via TCP/IP. This allows you to browse the web and send email at the same time because the web uses one port and email uses another. The port is represented by a number and there are thousands of available ports. Some have already been designated for specific functions like web browsing (80), email (25, 110, 143), FTP (20, 21), etc. If you are designing an app that will need to communicate with another app, you will need to find out what port the other app is using.

An SSLSocket has a Port property that can be assigned at design time or runtime but it must be assigned a value before you can connect to another computer. If you plan on initiating the connection, you must also set the Address property to the address (IP or resolvable name) of the computer to which you want to connect.

Linux and MacOS have built-in restrictions regarding port numbers. Ports below 1024 cannot be assigned by a user who is not running with "root" privileges. MacOS is configured so that a user cannot gain root privileges via the graphic user interface. Most users run with Admin privileges — not root — so you should use ports above 1024 for normal TCP/IP communications with MacOS or Linux because the socket cannot access port numbers below 1024. This is not a bug but a security feature that is built into these operating systems.

An SSLSocket control can only be connected to one connection (and thus app) at a time. If you need to maintain multiple connections simultaneously, you should use a ServerSocket, which is designed for this purpose.

Connecting to another computer

Once you have assigned a port and an IP address, you can connect to an app on the computer at that IP address, provided that the app is listening for TCP/IP connections on the port you have specified. To initiate a connection, you call the Connect method. Keep in mind that a connection is not necessarily established immediately after you call Connect. You have to wait for the app to which you are trying to connect to accept your connection. In addition, there could be general latency or other issues that take time to resolve.

TCPConnection.Connect

There are two ways to determine that you are connected. You can either wait until you receive a Connected event from your socket or test the return value of the IsConnected method. If you don 't wait for this feedback, you either cause the connection process to halt, resulting in a lost connection error (102), or an out of state error (106).

When the connection is established, the Connected event handler is called. If a connection is not established, an error occurs and the Error event handler is called.

Once a connection is established, your app can begin sending and receiving data with the app at the other end of the connection.

Listening for a connection from another computer

Your app can also listen for a connection request from another application. To do this, you use the Listen method:

TCPConnection.Listen

Once you put a socket into listen mode, it waits asynchronously for a connection request. Your app remains responsive while the socket is waiting and code continues to run.

When a connection is requested, the Connected event handler is called, which lets you know you have a connection.

Reading data

When the app at the other end of the connection sends data back to the TCPSocket that it's connected to, the DataAvailable event handler is called. The data that has been sent back goes into a place in the computet's memory called a buffer. The buffer is a place to store the data that has been sent by the other app.

In the DataAvailable event handler, you can use the Read or ReadAll methods to get some or all of the data (returned as a String) in the buffer. Use the Read method when you want to get a specific number of bytes (characters) from the buffer. If you want to get all the data in the buffer, use the ReadAll method. In both cases, the data returned from the buffer is removed from the buffer to make room for more incoming data. If you need to examine the data in the buffer without removing it from the buffer, use the LookAhead method.

This code in the DataAvailable event handler appends incoming data to a TextField:

TextField1.AddText(Me.ReadAll)

When you are reading text from an outside source, you may need to specify the text encoding. The text encoding is the scheme that maps each letter in the text to a numeric code. If the text comes from another app, operating system, or is in another language, you may need to specify which encoding was used. For more information on text encoding, refer to Understanding Text Encodings.

Both the Read and ReadAll methods take an optional parameter that enables you to specify the encoding. Use the Encodings object to get the desired encoding and pass it as a parameter. For example, the code above has been modified to specify that the incoming text uses the UTF8 encoding, a common standard:

TextField1.AddText(Me.ReadAll(Encodings.UTF8))

Writing data

You can send data to the application you are connected to at any time. You send data using the Write method. The data you wish to send must be a string. In this example, the text from a TextField is being sent via a TCPSocket control:

TCPConnection.Write(TextField1.Text)

If you need to send the text to an app that is expecting a specific text encoding, then you should convert the text to that encoding prior to sending it. Use the ConvertEncoding function to do this. Its parameters are the text to be converted and the text encoding to use. For example, the following line sends the text in the TextField using the MacRoman encoding:

TCPConnection.Write(ConvertEncoding(TextField1.Text, Encodings.MacRoman))

After all your data has been sent, the SendComplete event handler is called. As data is being sent, the SendProgress event handler is called so that you can tell how much data has been sent so far. Never assume how much data is sent between calls to the SendProgress event. It is normal to see this fluctuate.

If you are going to be sending small chunks of data across a network (especially a small network), it might make more sense to use the UDPSocket class instead.

Handling errors

Errors can occur while attempting to connect or while sending or receiving data. Errors are not always what they seem. For example, when the other computer closes the connection, an error is generated. When an error occurs, the Error event handler is executed. Errors are represented by numbers. The LastErrorCode property contains the number of the last error that occurred. See the SocketCore class for a complete list of error numbers.

Errors are simply ways to alert your app to conditions it may not have anticipated or be able to anticipate.

Closing the connection

When you are finished communicating and wish to disconnect from the other app, you do so by closing the connection. The connection is closed by calling the Close method. Suppose you have a Socket named “TCPConnection” that has established a connection. To close the connection, you can use the following code:

TCPConnection.Close

Other socket information

Destroying a socket

When you call the Connect or Listen methods your socket's reference count is incremented.

This means that the socket does not have to be owned by the anything (such as Window) in order for it to continue functioning. This is helpful in certain circumstances. For example, suppose you write your own socket subclass that implements all of the events for the socket, called MySocket. In the action event for a Button you use the following code:

Var s As New TCPSocket
s.Port = 7000
s.Address = "127.0.0.1"
s.Listen

Even after this event is completed, the socket stays active listening for connections. In fact, the socket stays active and alive until you specifically close it by either closing the connection locally or remotely.

Of course, the socket will also close when your app quits.