Goto Chapter: Top 1 2 3 4 5 6 7 8 9 Bib Ind
[Top of Book] [Contents] [Previous Chapter] [Next Chapter]

3 Using streams
3.1 Input-output TCP streams
3.1-1 IsInputOutputTCPStream
3.1-2 IsInputOutputTCPStreamRep
3.1-3 InputOutputTCPStream
3.2 Example of client-server communication via input-output TCP streams

### 3 Using streams

The package implements new kind of GAP input-output streams, called input-output TCP streams. Such streams are based on the functionality for the TCP/IP protocol usage provided by the GAP package IO, and may constitute an independent interest for GAP users.

Input-output TCP streams are intended to support all operations, implemented for streams in GAP. It is assumed that all existing code using streams should work with this kind of streams as well (please let us know, if you will notice that this is not the case!). We installed methods for input-output TCP streams to support the following operations: `ViewObj` (Reference: ViewObj), `PrintObj` (Reference: PrintObj), `ReadByte` (Reference: ReadByte), `ReadLine` (Reference: ReadLine), `ReadAll` (Reference: ReadAll), `WriteByte` (Reference: WriteByte), `WriteLine` (Reference: WriteLine), `WriteAll` (Reference: WriteAll), `IsEndOfStream` (Reference: IsEndOfStream), `CloseStream` (Reference: CloseStream), `FileDescriptorOfStream` (Reference: FileDescriptorOfStream), `UNIXSelect` (Reference: UNIXSelect).

#### 3.1 Input-output TCP streams

##### 3.1-1 IsInputOutputTCPStream

`‣ IsInputOutputTCPStream` | ( filter )

`IsInputOutputTCPStream` is a subcategory of `IsInputOutputStream` (Reference: IsInputOutputStream). Streams in the category `IsInputOutputTCPStream` are created with the help of the function `InputOutputTCPStream` (3.1-3) with one or two arguments dependently on whether they will be used in the client or server mode. Examples of their creation and usage will be given in subsequent sections.

##### 3.1-2 IsInputOutputTCPStreamRep

`‣ IsInputOutputTCPStreamRep` | ( filter )

This is the representation used for streams in the category `IsInputOutputTCPStream` (3.1-1).

##### 3.1-3 InputOutputTCPStream

`‣ InputOutputTCPStream`( desc ) | ( function )

`‣ InputOutputTCPStream`( host, port ) | ( function )

Returns: stream

The one-argument version must be called from the SCSCP server. Its argument desc must be a socket descriptor obtained using `IO_accept` (IO: IO_accept) function from the IO package (see the example below). It returns a stream in the category `IsInputOutputTCPStream` (3.1-1) which will use this socket to accept incoming connections. In most cases, the one-argument version is called automatically from `RunSCSCPserver` (5.2-1) rather then manually.

The version with two arguments, a string host and an integer port, must be called from the SCSCP client. It returns a stream in the category `IsInputOutputTCPStream` (3.1-1) which will be used by the client for communication with the SCSCP server running at hostname host on port port. In most cases, the two-argument version is called automatically from the higher level functions, for example, `EvaluateBySCSCP` (6.3-1).

#### 3.2 Example of client-server communication via input-output TCP streams

The following example demonstrates the low-level interaction between client and server using input-output TCP stream, and shows how such streams are created in the function `RunSCSCPserver` (5.2-1). It uses some functions from the IO package (see the IO manual for their description). We will show step by step what is happens on server and client (of course, if you will try this example, the numbers denoting descriptors may be different).

First, we will start two GAP sessions, one for the server, another one for the client. Now we enter the following commands on the server's side:

    gap> sock := IO_socket( IO.PF_INET, IO.SOCK_STREAM, "tcp" );
    3
    gap> lookup := IO_gethostbyname( "localhost" );
    rec( name := "localhost", aliases := [  ], addrtype := 2, length := 4,
      addr := [ "\177\000\000\>" ] )
    gap> port:=26133;
    26133
    gap> res := IO_bind( sock, IO_make_sockaddr_in( lookup.addr[1], port ) );
    true
    gap> IO_listen( sock, 5 );
    true
    gap> socket_descriptor := IO_accept( sock, IO_MakeIPAddressPort("0.0.0.0",0) );

After the last command you will not see the GAP prompt because the server starts to wait for an incoming connection. Now we go to the client's side and create an input-output TCP stream to the server. Here it can be created in one step:

    gap> clientstream:=InputOutputTCPStream( "localhost", 26133 );
    Creating a socket...
    Connecting to a remote socket via TCP/IP...

Now we are trying to connect to the server, and as soon as the connection will be established, the stream will be created at the client side, and we will see the output and the new GAP prompt:

    < input/output TCP stream to localhost >
    gap>

On the server you will get the socket descriptor and then you will be able to create a stream from it:

    4
    gap> serverstream := InputOutputTCPStream( socket_descriptor );
    < input/output TCP stream to socket >

Now we can write to this stream on the client side and then read from it on the server side and backwards. First, write on the client:

    gap> WriteLine( clientstream, "12345" );
    true

Now read and write on the server:

    gap> ReadLine( serverstream );
    "12345\n"
    gap> WriteLine( serverstream, "54321" );
    true

And finally we read on the client and close the stream:

    gap> ReadLine( clientstream );
    "54321\n"
    gap> CloseStream( clientstream );

and similarly close the stream on the server:

    gap> CloseStream( serverstream );

In this way one can organise remote communication between two copies of GAP in various ways. In subsequent chapters we explain how it is implemented using SCSCP to ensure compatibility not only with GAP but with any other SCSCP-compliant system.

[Top of Book] [Contents] [Previous Chapter] [Next Chapter]
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 Bib Ind

generated by GAPDoc2HTML