Deutsche Version   Deutsche Version


Version Adjustment
1.0 (2021-04-15) Initial version

Motivation

If you want to exchange data between two smartphones via TCP, this is only possible if one of the devices takes on the server role, i.e. accepts connection requests. The (TCP) client logs on to the (TCP) server (connect), the server accepts the request (accept). A valid TCP connection then exists, which enables data to be exchanged in both directions.


In­halts­ver­zeich­nis

Download

Usage

Overview

Character set

Disconnection

1. Sending the line end identifier with a delay

2. Sending test messages

Error handling

Reference

Properties

Character set

Error handling

Methods

Events

Example

URS TCP Client Test

Tools

Download

The UrsAI2TcpServer ZIP archive for download. The archive contains the source code, the compiled binary for uploading to the App Inventor and a sample application.

Usage

Notice:

The extension works perfectly if the smartphone and the remote station are in the same (local) network. If the smartphone is only connected via a cellular network, it is usually not reachable. The reason is that the smartphone is not directly connected to the Internet, but only to the local network of the mobile phone provider.

Mobilfunk-Verbindung

A device in your own LAN can be reached from outside via port forwarding on your own router (if necessary via DDNS). You won't be able to influence the provider's router. So sending from the smartphone to a device in the LAN works, the other way around is not possible.

The same also applies to TCP. If the smartphone is only connected to the cellular network, the connection can only be established from the smartphone. The device in the LAN must act as a server, it waits for an incoming connection request. The smartphone acts as a client, i.e. it initiates the connection. Once the connection has been set up, the routers have coordinated internally of addresses and ports. The data transfer is then possible in both directions.

Overview

The extension UrsAI2TcpServer enables TCP clients to establish a TCP connection to another Android device. Text messages can be exchanged via TCP. The text is transmittet and received line by line. A line is terminated by an end-of-line identifier (CR, LF, CRLF). If such an identifier is recognized upon receipt, the characters received up to that point are reported to the application via an event.

The Start method starts the server. It is now ready to accept connection requests from clients on the port specified by the LocalPort property. The IP address of the server can be obtained from the LocalHost property. Stop stops the server. If Start is called while the server is running, the server is first stopped and then restarted with the possibly changed settings. All settings for the server are taken over at startup. A change in the configuration only has an effect the next time Start is called.

The ServerStarted and ServerStopped events provide information about changes in the status. ServerStopped is also triggered if the server was stopped due to a (network) error. The event combination ServerStarted and ServerStopped is also triggered if the server does not even start due to an error. The IsRunning property provides information about whether the server is active.

If a client connects to the server, the ClientConnected event is triggered. Parameters are the client's IP address (ClientIP) and a numeric ID (ClientID) with which it is managed internally. If the client disconnects the ClientDisconnected event is triggered. The ConnectedClients property returns the number of clients currently connected to the server and the GetClientIDs function supplies a list with their IDs.

An incoming message from the client triggers the MessageReceived event. In addition to the actual message, the ClientID is also transferred so that the server can reply to the cleint directly via the Write and Writeln functions. Write puts the specified text into the output buffer. The immediate sending of the message is not guaranteed. Writeln writes the specified text in the output buffer and adds a end-of-line identifier which id defined by the LineDelimiterCrLf property. With true, CRLF (0x0D + 0x0A, for Windows-based servers) is appended and with false only LF (0x0A). Then the OutputStream.flush() method is called internally, which forces the data not yet sent to be sent.

Character set

The data is sent as a byte sequence. To do this, the text must be coded accordingly. The coding depends on the character set used. It is important that the sender and receiver use the same coding (the same character set). The character set used is determined by the Charset property. The name of the character set must be entered. To avoid spelling errors, the common names can be called up using the Charset_... properties.

Disconnection

With a TCP connection, it should actually be guaranteed that data is either sent correctly or an error is reported. Unfortunately, this is not the case with the Java implementation - at least the one on my smartphone (Java 7). Disconnections are only recognized after two write operations with a sufficiently long time interval (see  java-detect-lost-connection). This also applies when the remote terminal properly closes the connection (disconnect, close,...). The time interval is necessary because the Nagle's algorithm cannot be switched off (see Java Socket Option TCP_NODELAY). The call to OutputStream.flush() does not change this beavior, thow it should trigger an immediate dispatch.

This extension offers two possibilities to detect disconnections with a high probability.

1. Sending the line end identifier with a delay

Mostly the Write method does not send the data immediately, but buffers the data. The transfer is forced with Writeln. If the CrLfDelay property has the value 0, the end-of-line identifier is appended and the message is sent immediately. If the value is greater than 0, initially only the message is sent. The end-of-line identifier is sent after a delay that is determined by CrLfDelay. If the connection is interrupted, the sending of the end-of-line identifier triggers an error and thus the ClientDisconnected event is triggered. With my smartphone, a time delay of 200 ms was sufficient.

This mechanism reduces the data rate and increases the latency times. The decision must be made between security and performance.

2. Sending test messages

The TestConnection method sends two characters specified by the IgnoreTestChar property with a time delay (see above). The test character must be ignored by the recipient. Usually an invisible character is used. The character is specified as a numeric character code. The default setting is 6 (ACK, Acknowledge).

If the connection is interrupted, sending the second character triggers an error and thus the ClientDisconnected event.

Error handling

Errors are indicated by error numbers (ErrorCode). Errors are reported via the ErrorOccurred or ServerStopped events. Further information on the error can be retrieved by the LastError... properties

Code Meaning Text Comment
0 No error    
1 The server cannot be started. Cannot create server socket. Affected function Start. Usually the port is invalid or already in use. The error is reported via the ServerStopped event. Details can be obtained from the properties described in the Error handling section.
2 The server was stopped due to an error. Server stopped due to an error. The error is reported via the ServerStopped event. Details can be obtained from the properties described in the Error handling section.
3 Data could not be transmitted due to a connection error. Connection fault. Affected function Write, Writeln. The error is reported via the ServerStopped event. Details can be obtained from the properties described in the Error handling section.
4 The specified client ID is invalid. Invalid ClientID. Affected function Write, Writeln, Writeln. The error is reported via the ServerStopped event.

Reference

Properties

ConnectedClients
Returns the number of clients currently connected to the server.
CrLfDelay
Delay between the sending of the data and the end-of-line identifier (see Disconnection). The default setting is 200 milliseconds.
IgnoreTestChar
Character to be ignored when using method TestConnection (see Verbindungsabbruch). The numeric character code has to be entered. The default setting is 6 (ACK, Acknowledge).
IoTimeout
Time in milliseconds that is available for input and output operations. The default value is 1000 ms.
IsRunning
Returns the state of the server.
LineDelimiterCrLf
Specifies whether the sent message is terminated with a single "Line Feed" character ("\ n", 0x0A) or the combination "Carriage Return" + "Line Feed" ("\r\n", 0x0D+0x0A) (see function Writeln). If true, CRLF (0x0D+0x0A, for Windows-based servers) is appended and if false, only LF (0x0A) is appended
LocalHost
Gets the local IP address.
LocalPort
Specifies the port on which the server accepts connection requests
NICList
Returns a list of the IPv4 addresses of all network interfaces that have been set up. The list usually contains only one entry (see LocalHost).

Character set

Charset
Currently the character set. "US-ASCII", "UTF-8", "ISO-8859-1" (ISO-Latin-1), "UTF-16BE", "UTF-16BL" and "UTF-16" are accepted.
This value is evaluated when the connection is established and remains in effect for the entire duration of the connection.
Note: The character set is determined using the Java method Charset.forName, which is highly dependent on the implementation in the underlying operating system. So it may be that other character sets are valid. All character sets for which Charset.forName supplies valid results are accepted.
Charset_USASCII
Constant for character set US-ASCII.
Charset_UTF8
Constant for character set UTF-8.
Charset_ISO_Latin_1
Constant for character set ISO-8859-1 (ISO-Latin-1).
Charset_UTF16BE
Constant for character set UTF-16BE.
Charset_UTF16BL
Constant for character set UTF-16BL.
Charset_UTF16
Constant for character set UTF-16.

Error handling

LastAction
Name of the last action, e.g. "Start".
LastErrorCode
Error code of the last error that occurred (see below).
LastErrorMessage
Text for the code, e.g. "Invalid ClientID."
LastExecptionCause
Text of the Java exception that triggered the error.

Methods

GetClientIDs ()
Returns a list of the IDs of all clients connected to the server.
Start ()
Start the server. If this instruction is executed while the server is already running, it will first be stopped.
Stop ()
Stops the server.
TestConnection (ClientID, Delay)
Checks whether the connection to the specified client still exists. For this purpose, the character defined under IgnoreTestChar is sent twice with a time interval specified by Delay (milliseconds). If the connection no longer exists, the ClientDisconnected event is triggered when the second character is sent. If Delay <0, the value of CrLfDelay is used.
Write (ClientID, Message)
Writes the specified text to the output buffer of the specified client. The immediate sending of the message is not guaranteed.
Writeln (ClientID, Message)
Writes the specified text into the output buffer and adds a line end identifier. The type of the end-of-line identifier depends on the LineDelimiterCrLf property. If true, CRLF (0x0D + 0x0A, for Windows-based servers) is appended and if false, only LF (0x0A) is appended. Sending the message is forced.

Events

ErrorOccurred (ActionName, ErrorCode, ErrorMessage)
An error has occurred (see Error handling).
ClientConnected (CientID, ClientIP)
A client has connected to the server.  Parameters are the client's IP address (ClientIP) and a numeric ID (ClientID) with which it is managed internally.
ClientDisconnected (ClientID, ClientIP)
A client has disconnected from the server.  Parameters are the client's IP address (ClientIP) and a numeric ID (ClientID) with which it was managed internally.
MessageReceived (ClientID, Message)
A message was received from the specified client (ClientID).
ServerStarted ()
The server was started.
ServerStopped (ErrorCode)
The server has stopped. If the server was stopped due to an error, ErrorCode has a value greater than 0 (see Error handling).

Example

URS TCP Server Test

 This app sets up a TCP server that accepts connection requests on port 8083. Clients can connect to the server and send and receive text messages. After receiving a message, the server sends the text "Echo" plus the received text back to the client. The server can be tested with the UrsAI2TcpClient extension.

 

Note: Appropriate endpoint data must still be entered in the Designer.

Tools

I have gathered some tips for creating your own extensions: AI2 FAQ: Developing extensions.