• No results found

The port as seen by an external process

In document erlang book part1 pdf pdf (Page 138-143)

Miscellaneous Items

9.3 Code Replacement

9.4.3 The port as seen by an external process

The external program which executes outside the Erlang system (as started by

open_port({spawn, demo_server}, [{packet,2}])) can be written in any pro- gramming language supported by the host operating system. Our examples assume that we are running on a UNIX system and that the external program is a UNIX process which is programmed in C.

The C program which communicates with the Erlang process shown in Sec-

tion ?? is given in Program 9.3. This should be compiled and made into an executable file calleddemo_server.

/* demo_server.c */ #include <stdio.h> #include <string.h>

/* Message data are all unsigned bytes */ typedef unsigned char byte;

main(argc, argv) int argc; char **argv; { int len; int i; char *progname; byte buf[1000];

progname = argv[0]; /* Save start name of program */ fprintf(stderr, "demo_server in C Starting \n");

while ((len = read_cmd(buf)) > 0){ if(strncmp(buf, "echo", 4) == 0)

write_cmd("ohce", 4); else if(buf[0] == 10){

for(i=1; i < len ; i++) buf[i] = 2 * buf[i]; write_cmd(buf, len); }

} }

/* Read the 2 length bytes (MSB first), then the data. */ read_cmd(buf) byte *buf; { int len; if (read_exact(buf, 2) != 2) return(-1);

len = (buf[0] << 8) | buf[1]; return read_exact(buf, len); }

/* Pack the 2 bytes length (MSB first) and send it */ write_cmd(buf, len) byte *buf; int len; { byte str[2]; put_int16(len, str); if (write_exact(str, 2) != 2) return(-1);

return write_exact(buf, len); }

/* [read|write]_exact are used since they may return * BEFORE all bytes have been transmitted

*/ read_exact(buf, len) byte *buf; int len; { int i, got = 0;

Ports 129

do {

if ((i = read(0, buf+got, len-got)) <= 0) return (i);

got += i;

} while (got < len); return (len); } write_exact(buf, len) byte *buf; int len; { int i, wrote = 0; do {

if ((i = write(1, buf+wrote, len-wrote)) <= 0) return (i);

wrote += i;

} while (wrote < len); return (len); } put_int16(i, s) byte *s; { *s = (i >> 8) & 0xff; s[1] = i & 0xff; } Program 9.3

Program 9.3 reads the byte sequence which was sent to the Erlang port

with the expression len = read_cmd(buf) and sends data back to Erlangwith

write_cmd(buf, len).

File descriptor 0 is used to read data fromErlangand file descriptor 1 is used

to write data to Erlang. The C routines do the following:

read_cmd(buf)

Reads a single command from Erlang.

write_cmd(buf, len)

Writes a buffer of length len toErlang.

read_exact(buf, len)

write_exact(buf, len)

Writes lenbytes.

put_int16(i, s)

Packs a 16-bit integer into two bytes.

The routines read_cmd and write_cmd assumes that the protocol between the external server and Erlang consists of a two-byte header, giving the length of

the data packet to be exchanged, followed by the data itself. This is illustrated in Figure 9.1.

Erlang [0,5,1,2,3,4,5] C

Port ! {command, [1,2,3,4,5]} len = read(0, buf, 2) len = (buf[0]<<8)|buf[1]; read(0, buf, len);

Figure 9.1 Communication with a port

This particular protocol (two-byte header plus data) was used since the port was opened by evaluating:

open_port({spawn, demo_server}, [{packet, 2}])

9.5

Binaries

A binary is a data type which is used to store an area of untyped memory. A port is a binary port if the atom binary appears in the Settings list, given as the last argument to open_port/2. All messages which come from a binary port are binaries.

To illustrate the difference between a binary and normal port assume that we wish to send the string "hello" from an external process to the Erlang system

and that the ‘two-byte header plus data’ convention is used. The external program outputs the following byte sequence:

0 5 104 101 108 108 111

If the Erlang process which is connected to the port is a normal port, then

the message {Port, {data, [104,101,108,108,111]}} will be sent to the pro- cess. If the port had been a binary port then the message would have been

{Port, {data, Bin}}, where Bin is a binary data object of size 5, storing the bytes of the message. Note that in both cases there is no change to the external process which sends data to the port.

The advantage of having the port sending binary data objects instead of lists is that if the lists are long, it is considerably faster to build and send a binary data object than a list.

Binaries 131

term_to_binary(T)

Converts the term T to a binary. The resulting binary data object is a representation of the term in the external term format.

binary_to_term(Bin)

Is the inverse ofterm_to_binary/1.

binary_to_list(Bin)

Converts the binary Bin to a list of integers.

binary_to_list(Bin, Start, Stop)

Converts a portion of the binary Bin into a list of characters, starting at position Start, and stopping at position Stop. The first position of the binary has position 1.

list_to_binary(Charlist)

Converts Charlist into a binary data object. This is not the same as

term_to_binary(Charlist). This BIF builds a binary object containing the bytes in Charlist as opposed to term_to_binary(Charlist) which builds a binary object containing the bytes of the external term format of theterm Charlist.

split_binary(Bin, Pos)

Builds two new binaries, as if Bin had been split at Pos. Returns a tuple consisting of the two new binaries. For example:

1> B = list_to_binary("0123456789"). #Bin 2> size(B). 10 3> {B1,B2} = split_binary(B,3). {#Bin,#Bin} 4> size(B1). 3 5> size(B2). 7 concat_binary(ListOfBinaries)

Returns a new binary which is formed by the concatenation of the binaries inListOfBinaries.

In addition the guard test binary(X) succeeds if X is a binary data object. Binaries are primarily used for code loading in a network, but can also be used by applications that shuffle large amounts of raw data such as audio or video data. It is possible to efficiently input very large amounts of binary data through a port, work with the data , and then at a later stage, output it to another or the same port.

In document erlang book part1 pdf pdf (Page 138-143)

Related documents