Messaging to other service

<div align="Left"><font size="1" face="Verdana" color="#000000"> We are using ver 8.3 currently in a character interface system, and want to be able to transfer information between our system and an EFTPOS server using TCP/IP messaging. We know the IP addresses and sockets, message format etc, but how can I send and receive messages from Progress 4GL. If necessary we could write an interface in C, but would rather not add extra layers.

All help will be appreciated
David</font></div>
 

Chris Kelleher

Administrator
Staff member
<div align="Left"><font size="1" face="Verdana" color="#000000"> Hi David-

I would strongly recommend upgrading to Version 9.1. Not only are there a ton of performance and feature enhancements, but there is also native support for reading and writing to TCP/IP Sockets. If you can't upgrade, then you will have to do something in 'C' to handle this and use the Progress INPUT/OUTPUT THROUGH statement.

Here is alot more about socket support in Progress, written by Gus Bjorklund

<BLOCKQUOTE><font size="1" face="Arial, Verdana">quote:</font><HR>
Support for TCP/IP Sockets in the 4GL

From the client perspective, the 4GL provides the ability to connect a socket to a port, read from a socket, write to a socket, support socket events and close the socket. From the server perspective, the 4GL provides, in addition to the client capabilities, the ability for the server to listen for client side connections.

Two new handle types have been introduced: the SOCKET object for the client side and the SERVER-SOCKET object for the connection-oriented server side.

The SOCKET Object

The new SOCKET object handle supports the following new and modified statements, attributes and methods:

CREATE SOCKET Statement
BYTES-READ Attribute
BYTES-WRITTEN Attribute
REMOTE-HOST Attribute
LOCAL-HOST Attribute
REMOTE-PORT Attribute
LOCAL-PORT Attribute
SENSITIVE Attribute
CONNECT( ) Method
SET-READ-RESPONSE-PROCEDURE( ) Method
READ( ) Method
WRITE( ) Method
DISCONNECT( ) Method
CONNECTED( ) Method
GET-BYTES-AVAILABLE( ) Method
SET-SOCKET-OPTION( ) Method
GET-SOCKET-OPTION( ) Method

CREATE SOCKET Statement

Creates an instance of a SOCKET object and assigns its handle value to the handle variable specified. It is through this object that the application can write to and read from a socket.

DELETE OBJECT Statement

Deletes an instance of an object. A SOCKET object may be supplied as a handle to this statement.

BYTES-READ Attribute

Returns the number of bytes read from the socket via the last READ( ) method. If the last READ( ) method failed, this attribute will return 0.

BYTES-WRITTEN Attribute

Returns the number of bytes written to the socket via the last WRITE( ) method. If the last WRITE( ) method failed, this attribute will return 0.

REMOTE-HOST Attribute

Indicates the IP (Internet Protocol) address of the machine the SOCKET object is communicating with. When a server and client successfully establish a connection, both the server and client have a SOCKET object that identifies this connection. On the client, this attribute returns the IP address of the server and on the server, this attribute returns the IP address of the client. If the CONNECT method failed, this attribute returns the unknown (?) value.

LOCAL-HOST Attribute

Indicates the IP (Internet Protocol) address of the machine the SOCKET object is communicating with. When a server and client successfully establish a connection, both the server and client have a SOCKET object that identifies this connection. On the client and on the server, this attribute returns the IP address of the machine which is making the request. If the CONNECT method failed, this attribute returns the unknown (?) value.

REMOTE-PORT Attribute

Indicates the port number of the socket. When a server and client successfully establish a connection, both the server and client have a SOCKET object that identifies this connection. On the client, this attribute returns the port number used on the server machine for this socket connection. On the server, this attribute returns the port number used on the client machine for this socket connection. If the CONNECT failed, this attribute returns the unknown (?) value.

LOCAL-PORT Attribute

Indicates the port number of the socket. When a server and client successfully establish a connection, both the server and client have a SOCKET object that identifies this connection. On the client, this attribute returns the port number used on the client machine for this socket connection. On the server, this attribute returns the port number used on the server machine for this socket connection. If the CONNECT failed, this attribute returns the unknown (?) value.

TYPE Attribute

Returns the type of the handle, which in this case is a character string value of "SOCKET".

NAME Attribute

A string identifier for the socket object. This attribute may be set to any arbitrary value. Progress will use this name when generating error messages associated with this object.

SENSITIVE Attribute

Indicates whether the object can receive events. By default, this attribute is set to TRUE when a SOCKET object is created. Setting the SENSITIVE attribute to FALSE causes the object not to respond to READ-RESPONSE events.

NOTE: The SENSITIVE attribute is used by an application which controls when data is received on a socket. If an application knows it will not receive data on a socket during some period of time, it should set this attribute to FALSE. This allows the application to run more efficiently since Progress does not monitor the socket if its SENSITIVE attribute is set to FALSE. Data
can still be written to an insensitive socket object. When the attribute is set to TRUE, Progress checks the socket for data.

CONNECT( ) Method

Creates an association between a Progress SOCKET handle and a specified port.

SET-READ-RESPONSE-PROCEDURE( ) Method

This method is used to identify the name of the procedure that is invoked when a READ event occurs.

READ( ) Method

Reads a specified number of bytes of data from the socket into a buffer specified by a MEMPTR expression that identifies where the data which is read from the socket should be stored.

This read statement is a blocking read. If mode is READ-EXACT-NUM, this method returns when it has either read the requested number of bytes from the socket or an error occurs. If mode is READ-AVAILABLE, this method returns when it has read as many bytes as are available on the socket, up to the requested number of bytes, or an error occurs.

If the READ( ) method succeeds, the variable buffer is assigned the information which is read from the socket. It is possible that the socket will not contain the specified number of bytes of data which were requested.
The BYTES-READ attribute can be used to determine the number of bytes read from the socket.

This method expects buffer to identify a MEMPTR variable which already has a region of memory associated with it. The developer must call the SET-SIZE statement to allocate memory and associate it with a MEMPTR
variable. It is the responsibility of the developer to free this memory, also via the SET-SIZE statement. The READ method will fail if the size of buffer is less than bytes-to-read.

WRITE( ) Method

Writes a specified number of bytes of data to the socket from a buffer specified by a MEMPTR expression which contains the data which should be written to the socket.


DISCONNECT( ) Method

Closes the socket and deletes the association between a Progress SOCKET handle and its associated port.

CONNECTED( ) Method

Indicates if a SOCKET handle is currently connected to a port.

GET-BYTES-AVAILABLE( ) Method

Indicates the number of bytes available for reading from the socket.

SET-SOCKET-OPTION( ) Method

Sets the specified socket option. Progress supports setting the TCP-NODELAY and SO-LINGER options.

GET-SOCKET-OPTION( ) Method

Retrieves the specified socket option. TCP supports a number of socket options.


The SERVER-SOCKET Object

The new SERVER-SOCKET object handle supports the following new and modified statements, attributes and methods:

CREATE SERVER-SOCKET Statement
TYPE Attribute
NAME Attribute
SENSITIVE Attribute
ENABLE-CONNECTIONS( ) Method
SET-CONNECT-PROCEDURE( ) Method
DISABLE-CONNECTIONS( ) Method

CREATE SERVER-SOCKET Statement

Creates an instance of a SERVER-SOCKET object and assigns its handle to the
handle variable specified. It is through this object that the connection-oriented server application can allow connections to a port.


TYPE Attribute

Returns the type of the handle, in this case, a character string value of "SERVER-SOCKET".

NAME Attribute

A string identifier for the server-socket object This attribute may be set to any arbitrary value. Progress will use this name when generating error messages associated with this object.

SENSITIVE Attribute

Indicates whether the object can receive events. By default, this attribute is set to TRUE when a SERVER-SOCKET object is created. Setting the SENSITIVE attribute to FALSE causes the object not to respond to CONNECT
events.

ENABLE-CONNECTIONS( ) Method

Identifies that a connection-oriented server is ready to receive connections on a port.

Neither an AppServer nor a WebSpeed agent can act as a socket server, since they are already listening on a port. ENABLE-CONNECTIONS is only valid from batch clients, GUI clients and character clients. This method will generate an error if it is called from an invalid application or called multiple times.

SET-CONNECT-PROCEDURE( ) Method

This method is used to identify the name of the procedure that is invoked when a CONNECT event occurs.

DISABLE-CONNECTIONS( ) Method

Identifies that a connection-oriented server no longer wants clients to connect to a port. The server will not receive any new connection events for this port but all existing sockets are still valid.

SELF Handle

If referenced within a READ-RESPONSE event procedure, then SELF is the SOCKET handle associated with the connection that received the message. If referenced within the CONNECT event procedure, then SELF is the
SERVER-SOCKET handle.

SESSION System Handle

The modified SESSION System Handle supports the following new attributes:

New FIRST-SOCKET Attribute
New LAST-SOCKET Attribute
New FIRST-SERVER-SOCKET Attribute
New LAST-SERVER-SOCKET Attribute

Socket Events

READ-RESPONSE Event

Progress looks for events to execute in the context of U/I blocking statements. During this processing if Progress detects that data is available on a socket or that the remote end closed its socket, the READ-RESPONSE event is generated and the READ-RESPONSE event procedure is invoked.

The SET-READ-RESPONSE-PROCEDURE( ) method is used to associate an event procedure with a SOCKET object. Progress invokes this procedure whenever it detects that data is available on the socket or that the remote end of the socket has closed its end of the socket. In this procedure, the SELF handle identifies the affected SOCKET object.

CONNECT Event

Whenever it detects that a client has connected to a port that the server has enabled connections to, Progress will generate a CONNECT event and invoke the connect event procedure.

The SET-CONNECT-PROCEDURE( ) method is used to associate a connect event procedure with a SERVER-SOCKET object. The connect event procedure MUST accept one input parameter of type HANDLE. This is the handle to the implicitly created SOCKET object for this connection. It is via this SOCKET object that the server communicates with the client.

List Functions

The following functions have been modified to include socket information in the returned lists:

Modified LIST-EVENTS function
Modified LIST-QUERY-ATTRS function
Modified LIST-SET-ATTRS function
Modified LIST-WIDGETS function

Marshalling and Unmarshalling Transmitted Data

4GL developers using sockets have two major tasks: transmitting data through a socket and marshaling or unmarshalling the data they send or receive. The SOCKET and SERVER-SOCKET objects enable developers to send and receive data through a socket. This section tells how you can marshal and unmarshal data,
i.e., put data together in the format expected by the receiver before sending it and extract data from the incoming stream.

Socket:Read( ) and Socket:Write( ) use MEMPTR variables for the buffers they receive or send. This means that you can use the functions that operate on MEMPTRs to put data into and get data out of the buffers. The Progress 4GL supports the following new and modified functions for use in:

General data marshalling and unmarshalling:
Modified GET-DOUBLE Function
Modified GET-FLOAT Function
Modified GET-LONG Function
Modified GET-SHORT Function
Modified GET-UNSIGNED-SHORT Function
New GET-BYTES Function
Modified GET-STRING Function
Modified PUT-DOUBLE Statement
Modified PUT-FLOAT Statement
Modified PUT-LONG Statement
Modified PUT-SHORT Statement
Modified PUT-UNSIGNED-SHORT Statement
New PUT-BYTES Statement
Modified PUT-STRING Statement
Modified DATE Function
Byte ordering:
New SET-BYTE-ORDER statement
New GET-BYTE-ORDER function
Bit manipulation:
New GET-BITS function
New PUT-BITS statement

NOTE: In addition to the above statements and functions, the current GET-BYTE function and PUT-BYTE statement are available to be used in marshalling and unmarshalling data although they have not been changed.

Examples

The following very simple examples show the two sides of a socket communication.

On the Server Side

This example uses a fixed message size of 128 bytes. All character data is transmitted in ibm850 codepage.
<HR></BLOCKQUOTE>

<BLOCKQUOTE><font size="1" face="Arial, Verdana">code:</font><HR><pre>
DEFINE VARIABLE log as LOGICAL.
DEFINE VARIABLE hSS AS HANDLE.

CREATE SERVER-SOCKET hSS NO-ERROR.
log = hSS:ENABLE-CONNECTIONS("-H mach1 -S 1234").
IF log THEN
hSS:SET-CONNECT-PROCEDURE("connectionHandler",THIS-PROCEDURE).

WAIT-FOR WINDOW-CLOSE OF CURRENT-WINDOW.

PROCEDURE connectionHandler:
DEFINE INPUT PARAMETER hSocket AS HANDLE.
DEFINE VARIABLE m1 AS MEMPTR.
DEFINE VARIABLE ch AS CHARACTER INITIAL "This is a simple test".

SET-SIZE(m1) = 128.
CODEPAGE-CONVERT(ch,"ibm850",SESSION:CHARSET).
PUT-STRING(m1,1) = ch.
log = HSocket:WRITE(m1, 1, 128) NO-ERROR.

HSocket:SET-READ-RESPONSE-PROCEDURE("readHandler",THIS-PROCEDURE).
SET-SIZE(m1) = 0.
END PROCEDURE.

PROCEDURE readHandler:
DEFINE VARIABLE m1 AS MEMPTR.
DEFINE VARIABLE ch AS CHARACTER.

SET-SIZE(m1) = 128.
SELF:READ(m1,1,128).

ch = GET-STRING(m1,1).
CODEPAGE-CONVERT(ch,SESSION:CHARSET,"ibm850").
MESSAGE ch VIEW-AS ALERT-BOX.
SET-SIZE(m1) = 0.
END PROCEDURE.

[/code]

<BLOCKQUOTE><font size="1" face="Arial, Verdana">quote:</font><HR>
On the Client Side

This example uses a fixed message size of 128 bytes. All character data is transmitted in ibm850 codepage.
<HR></BLOCKQUOTE>

<BLOCKQUOTE><font size="1" face="Arial, Verdana">code:</font><HR><pre>
DEFINE VARIABLE log as LOGICAL.
DEFINE VARIABLE hSocket AS HANDLE.

CREATE SOCKET hSocket NO-ERROR.
log = hSocket:CONNECT("-H mach1 -S 1234").
IF log THEN
hSS:SET-READ-RESPONSE-PROCEDURE("readHandler",THIS-PROCEDURE).

WAIT-FOR WINDOW-CLOSE OF CURRENT-WINDOW.

PROCEDURE readHandler:
DEFINE VARIABLE m1 AS MEMPTR.
DEFINE VARIABLE ch AS CHARACTER.

SET-SIZE(m1) = 128.
SELF:READ(m1,1,128).

ch = GET-STRING(m1, 1).
CODEPAGE-CONVERT(ch,SESSION:CHARSET,"ibm850").
MESSAGE ch VIEW-AS ALERT-BOX.

ch = "Received".
CODEPAGE-CONVERT(ch,"ibm850",SESSION:CHARSET).
PUT-STRING(m1, 1) = ch.
log = HSocket:WRITE(m1,1,128) NO-ERROR.

SET-SIZE(m1) = 0.
END PROCEDURE.
[/code]

<BLOCKQUOTE><font size="1" face="Arial, Verdana">quote:</font><HR>
|regards,
|gus
|-------------------------------------------------------------------
| Gus Bjorklund, Wizard, Progress Software Corporation, Bedford MA.
| Purveyors of the finest rdbms on the third planet from the sun.
|
| "Beta testing is for sissies."

<HR></BLOCKQUOTE></font></div>

------------------
Chris Schreiber
ProgressTalk.com Manager
chris@fast4gl.com
 
<div align="Left"><font size="2" face="Arial" color="#000000"> Thanks for the help, V9.1 sounds really useful, but we can't upgrade at the moment. We are using ver 8.3 running in a character interface on a Unix machine. The server we need to connect to will be located on an NT box. Obviously we can use input-output through ..... But through what will be the question. Are there any useful UNIX utilities anyone knows of? Can you point me in a useful direction. I can program in so that is a possible direction, although I haven't ever done anything like this.</font></div>
 

Chris Kelleher

Administrator
Staff member
<div align="Left"><font size="2" face="Arial" color="#000000"> David-

I would search around the Internet for some 'C' source code you could use as a starting point. Actually something like this shouldn't take too much code anyway. Sorry I can't point you to something specific, but I have never had a need for this myself.

HTH.

-Chris</font></div>

------------------
Chris Schreiber
ProgressTalk.com Manager
chris@fast4gl.com
 
Top