内容简介:在Erlang中,有很多种方式去实现与其他语言的交互,常见的几种方式有后面几种难度都是有的,也使用了比较复杂的C/C++,而且比较容易出现问题。TCP的方式是通过网络协议,个人也不是很喜欢,那就剩下Port方式去连接Erlang服务器。
title: 实现Golang和Erlang的连接(Port) categories: Golang
在Erlang中,有很多种方式去实现与其他语言的交互,常见的几种方式有
- 使用TCP协议交互
- 使用Port
- 使用Erl_Interface方式去实现
- CNode
- NIF
后面几种难度都是有的,也使用了比较复杂的C/C++,而且比较容易出现问题。TCP的方式是通过网络协议,个人也不是很喜欢,那就剩下Port方式去连接Erlang服务器。
在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
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- php实现mysql连接池效果实现代码
- java并发实战:连接池实现
- Django+Vue实现WebSocket连接
- 实现WebRTC P2P连接
- Swoole MySQL 连接池的实现
- Swoole Redis 连接池的实现
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Mobilizing Web Sites
Layon, Kristofer / 2011-12 / 266.00元
Everyone has been talking about the mobile web in recent years, and more of us are browsing the web on smartphones and similar devices than ever before. But most of what we are viewing has not yet bee......一起来看看 《Mobilizing Web Sites》 这本书的介绍吧!