我有一个简单的从Erlang到Golang的端口示例,将数据从Erlang传递到Golang并回显响应。
问题是我可以传输的数据量似乎限制为2 ^
8字节(请参见下文)。我认为问题可能出在Golang端(没有创建足够大的缓冲区),但是用bufio.NewReaderSize替换bufio.NewReader无效。因此,我现在认为问题可能出在Erlang一方。
我该怎么做才能增加缓冲区大小/能够回显大于2 ^ 8字节的消息?
TIA
justin@justin-ThinkPad-X240:~/work/erlang_golang_port$ erl -pa ebin
Erlang/OTP 17 [erts-6.4.1] [source] [64-bit] [smp:4:4] [async-threads:10] [kernel-poll:false]
Eshell V6.4.1 (abort with ^G)
1> port:start("./echo").
<0.35.0>
2> port:ping(65000).
65000
3> port:ping(66000).
** exception error: bad argument
in function port:call_port/1 (port.erl, line 20)
4> port:start("./echo").
<0.40.0>
5> port:ping(66000).
65536
go
package main
import (
"bufio"
"os"
)
const Delimiter = '\n'
func main() {
// reader := bufio:NewReader(os.Stdin)
reader := bufio.NewReaderSize(os.Stdin, 1677216) // 2**24;
bytes, _ := reader.ReadBytes(Delimiter)
os.Stdout.Write(bytes[:len(bytes)-1])
}
Erlang
-module(port).
-export([start/1, stop/0, init/1]).
-export([ping/1]).
-define(DELIMITER, [10]).
start(ExtPrg) ->
spawn(?MODULE, init, [ExtPrg]).
stop() ->
myname ! stop.
ping(N) ->
Msg=[round(65+26*random:uniform()) || _ <- lists:seq(1, N)],
call_port(Msg).
call_port(Msg) ->
myname ! {call, self(), Msg},
receive
{myname, Result} ->
length(Result)
end.
init(ExtPrg) ->
register(myname, self()),
process_flag(trap_exit, true),
Port = open_port({spawn, ExtPrg}, []),
loop(Port).
loop(Port) ->
receive
{call, Caller, Msg} ->
Port ! {self(), {command, Msg++?DELIMITER}},
receive
{Port, {data, Data}} ->
Caller ! {myname, Data}
end,
loop(Port);
stop ->
Port ! {self(), close},
receive
{Port, closed} ->
exit(normal)
end;
{'EXIT', Port, _Reason} ->
exit(port_terminated)
end.
如果start_link
改为使用,您将在第一个命令后看到端口崩溃:
1> port:start('go run port.go').
<0.118.0>
2> port:ping(65000).
65000
** exception error: port_terminated
如果将Go代码更改为在循环中运行,则可以避免此崩溃:
func main() {
for {
// reader := bufio:NewReader(os.Stdin)
reader := bufio.NewReaderSize(os.Stdin, 1677216) // 2**24;
bytes, _ := reader.ReadBytes(Delimiter)
os.Stdout.Write(bytes[:len(bytes)-1])
}
}
现在我们可以看到另一个有趣的结果:
33> c(port).
{ok,port}
40> port:ping(66000).
65536
41> port:ping(66000).
464
42> port:ping(66000).
65536
43> port:ping(66000).
464
现在我们可以看到实际上没有任何数据丢失,它只是缓存在端口中。由于您尚未指定成帧协议(使用{packet, N}
或{line,N}
您自己负责收集数据。似乎Erlang端口的内部缓冲区大小为64K(尽管我没有找到有关此文件的文档,也无法更改它)。
如果将接收更改为在返回之前获取所有数据,则每次将占用每个字节:
loop(Port) ->
receive
{call, Caller, Msg} ->
Port ! {self(), {command, Msg++?DELIMITER}},
Caller ! {myname, receive_all(Port, 10)},
loop(Port);
stop ->
Port ! {self(), close},
receive
{Port, closed} ->
exit(normal)
end;
{'EXIT', Port, _Reason} ->
exit(port_terminated)
end.
receive_all(Port, Timeout) -> receive_all(Port, Timeout, []).
receive_all(Port, Timeout, Data) ->
receive
{Port, {data, New}} ->
receive_all(Port, Timeout, [New|Data])
after Timeout ->
lists:flatten(lists:reverse(Data))
end.
运行此命令,我们得到:
1> c(port).
{ok,port}
2>
3> port:start('go run port.go').
<0.311.0>
4> port:ping(66000).
66000
5> port:ping(66000).
66000
6> port:ping(66000).
66000
问题内容: 我正在尝试为Erlang编写Golang驱动程序,可通过Erlang端口访问。 我从Erlang C端口示例开始,该示例运行良好: http://www.erlang.org/doc/tutorial/c_port.html 现在,我正在尝试将C代码移植到Golang。只是尝试使用“ \ n”作为分隔符来回显简单的“ Hello World \ n”消息。 所以我的Golang代码如下
我想在我的小libgdx游戏中使用框架缓冲区。 游戏使用了,我修改了s摄像头,使其使用50宽31高的视口。然后我将的投影矩阵设置为。这样做,我有一个分辨率独立的游戏,我可以使用我自己的“世界单位”,而不是使用像素。 但是现在,如果我创建一个,我必须给它一个大小。我必须给它摄像机视口的大小还是屏幕的大小(以像素为单位)? 而且,当我渲染的东西,我可以渲染他们在,这意味着渲染在几乎在游戏窗口的中间?
请注意:虽然这个问题特别提到了Dropwizard,但我相信任何有泽西/JAX-RS经验的人都应该能够回答这个问题,因为我可以想象Dropwizard只是在幕后遵循泽西/JAX-RS约定。 我有一个Dropwizard服务,它用JSON编写,工作非常出色。 现在我想将其切换为读/写二进制数据(以最小化网络带宽)。我看到了Dropwizard Protobuf库,但我对在Dropwizard中实现二
问题内容: 我有: 哪个追加到缓冲区,是否可以写入缓冲区的开头? 问题答案: 由于基础不是从导出的,因此您可以使用: 试试这个The Go Playground: 输出:
问题内容: 构造函数中的缓冲区大小是什么意思? 当我编写程序时: 输出: 然后,缓冲区大小是什么意思,正如我希望的那样,它只能读取两个字符。但事实并非如此。 问题答案: 顾名思义,缓冲输入。这意味着它会在将输入源传递给您之前从输入源读取到缓冲区。此处的缓冲区大小是指其缓冲的字节数。 从大多数来源读取输入非常慢。仅2个字节的缓冲区将损害性能,因为您的程序很可能大部分时间都在等待输入。缓冲区大小为2时
虽然我认为这个API更改请求在我来之前就已经存在了,所以我不会建议任何人屏住呼吸。