实现Golang和Erlang的连接(Port)

栏目: Erlang · 发布时间: 5年前

内容简介:在Erlang中,有很多种方式去实现与其他语言的交互,常见的几种方式有后面几种难度都是有的,也使用了比较复杂的C/C++,而且比较容易出现问题。TCP的方式是通过网络协议,个人也不是很喜欢,那就剩下Port方式去连接Erlang服务器。

title: 实现Golang和Erlang的连接(Port) categories: Golang

在Erlang中,有很多种方式去实现与其他语言的交互,常见的几种方式有

  1. 使用TCP协议交互
  2. 使用Port
  3. 使用Erl_Interface方式去实现
  4. CNode
  5. NIF

后面几种难度都是有的,也使用了比较复杂的C/C++,而且比较容易出现问题。TCP的方式是通过网络协议,个人也不是很喜欢,那就剩下Port方式去连接Erlang服务器。

Erlang的官方文档中对Port的介绍

在Erlang中使用Port非常简单,实际上就是通过标准输入输出流与外部程序就行交互。

现在我还是沿用官方文档中代码,仅做部分修改,实现Erlang与Golang的交互。

%% complex1.erl

-module(complex1).
-export([start/1, stop/0, init/1]).
-export([foo/1, bar/1]).

start(ExtPrg) ->
    spawn(?MODULE, init, [ExtPrg]).
stop() ->
    complex ! stop.

foo(X) ->
    call_port({foo, X}).
bar(Y) ->
    call_port({bar, Y}).

call_port(Msg) ->
    complex ! {call, self(), Msg},
    receive
	{complex, Result} ->
	    Result
    end.

init(ExtPrg) ->
    register(complex, self()),
    process_flag(trap_exit, true),
    %% 注意{packet, 2}代表的是用2个字节表示传输的
    %% Port = open_port({spawn, ExtPrg}, [{packet, 2}]),
    %% 在这里不去处理这个数据头,不需要这个参数
    Port = open_port({spawn, ExtPrg}, []),
    loop(Port).

loop(Port) ->
    receive
	{call, Caller, Msg} ->
	    Port ! {self(), {command, encode(Msg)}},
	    receive
		{Port, {data, Data}} ->
		    Caller ! {complex, decode(Data)}
	    end,
	    loop(Port);
	stop ->
	    Port ! {self(), close},
	    receive
		{Port, closed} ->
		    exit(normal)
	    end;
	{'EXIT', Port, Reason} ->
	    exit(port_terminated)
    end.

%% 进行编码,将数据转成2进制
encode({foo, X}) -> <<1:8, X:8>>;
encode({bar, Y}) -> <<2:8, Y:8>>].

%% 这里有点特别,
decode(Data) -> erlang:list_to_binary(Data).

对于Golang,需要读取标准输入流的数据,这里我用bufio处理下(其实也没有太多必要,哈哈哈)。因为这里没有使用数据流的头部来记录数据的长度,所以默认将数据长度设置为2的byte数组。

// port.go

package main

import (
	"bufio"
	"os"
)

func main() {
	reader := bufio.NewReader(os.Stdin)
	writer := bufio.NewWriter(os.Stdout)
	for {
		buff := make([]byte, 2)
		_, err := reader.Read(buff)
		if err != nil {
			panic(err.Error())
		}
		switch int(buff[0]) {
		case 1:
			buff[1] = byte(foo(int(buff[1])))
		case 2:
			buff[1] = byte(bar(int(buff[1])))
		}
        writer.Write(buff[1:2])
        // 这里需要注意,要用Flush进行处理,否则erlang端收不到信息
		writer.Flush()
	}
}

func foo(num int) int {
	return num + 1
}

func bar(num int) int {
	return 2 * num
}

使用

步骤1 编译port.go

go build port.go

步骤2 运行Erlang虚拟机

unix> erl
Erlang (BEAM) emulator version 4.9.1.2

Eshell V4.9.1.2 (abort with ^G)
1> c(complex1).
{ok,complex1}

步骤3 运行

2> complex1:start("extprg").
<0.34.0>
3> complex1:foo(3).
4
4> complex1:bar(5).
10
5> complex1:stop().
stop

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Flask Web开发:基于Python的Web应用开发实战

Flask Web开发:基于Python的Web应用开发实战

[美] Miguel Grinberg / 安道 / 人民邮电出版社 / 2014-12 / 59.00元

本书不仅适合初级Web开发人员学习阅读,更是Python程序员用来学习高级Web开发技术的优秀参考书。 • 学习Flask应用的基本结构,编写示例应用; • 使用必备的组件,包括模板、数据库、Web表单和电子邮件支持; • 使用包和模块构建可伸缩的大型应用; • 实现用户认证、角色和个人资料; • 在博客网站中重用模板、分页显示列表以及使用富文本; • 使用基于......一起来看看 《Flask Web开发:基于Python的Web应用开发实战》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具