首页 > Erlang并发教程 > 10.8 Erlang并发编程-外部进程眼中的端口
2013
11-19

10.8 Erlang并发编程-外部进程眼中的端口

BACK TOP文章索引

  1. 外部进程眼中的端口
  2. 共1条评论

外部进程眼中的端口

程序9.3

/* 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;

    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;
}

程序9.3通过表达式len = read_cmd(buf)读取发送至Erlang端口的字节序列,并用write_cmd(buf, len)将数据发回Erlang。

文件描述符0用于从Erlang读取数据,而文件描述符1用于向Erlang写入数据。各个C函数的功能如下:

read_cmd(buf)

从Erlang读取一条命令。

write_cmd(buf, len)

向Erlang写入一个长度为len的缓冲区。

read_exact(buf, len)

读取len个字节。

write_exact(buf, len)

写入len个字节。

put_int16(i, s)

将一个16位整数打包为两个字节。

函数read_cmdwrite_cmd假设外部服务和Erlang间的协议由一个指明数据包长度的双字节包头和紧随的数据构成。如图9.1所示。

../_images/9.1.png图9.1 端口通讯

之所以使用这种协议(双字节包头加数据)是由于端口是以如下方式打开的:

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

10.8 Erlang并发编程-外部进程眼中的端口》有 1 条评论

  1. 黑天鹅港呢,零号他们到哪去了

留下一个回复

你的email不会被公开。