远程函数调用最简单的网络协议?
Most simple network protocol for a remote function call?
我正在寻找最简单的协议来编写远程函数调用,例如从 Matlab 到 Julia。
[out1, out2, ...] = jlcall(socket, fname, arg1, arg2, ...);
fname是一个字符串,所有其他输入和输出变量都是数值数组(或其他双方都知道的结构)在Linux,Windows作为选项。
- 客户端:打开连接、阻塞、打包和传输
- 服务器:接收、解包、处理、打包并传回
- 客户端:接收、解包、关闭连接并继续
我seen(tcp、zmq)的解决方案是用旧版本构建的,不再有效。
协议可以(应该?)限于执行 pack/transmit - receive/unpack 工作。
更新
这是我使用管道得出的结论:
function result = jlcall(varargin)
% result = jlcall('fname', arg1, arg2, ...)
% call a Julia function with arguments from Matlab
if nargin == 0 % demo
task = {'foo', 2, 3}; % demo fun, defined in jsoncall.jl
else
task = varargin;
end
% create pipe and write function and parameter(s) to pipe
pipename = tempname;
pipe = java.io.FileOutputStream(pipename);
pipe.write(uint8(jsonencode(task)));
pipe.close;
% run Julia and read result back
system(sprintf('julia jsoncall.jl %s', unixpath(pipename)))
fid = fopen(pipename, 'r');
c = fread(fid);
result = jsondecode(char(c'));
fclose(fid);
function path_unix = unixpath(path_pc)
%convert path to unix version
path_unix = path_pc;
path_unix(strfind(path_unix,'\'))='/';
# jsoncall.jl
using JSON3 # get JSON3.jl from repository first
function foo(a,b) # demo function
a+b, a*b
end
jsonfile = ARGS[1] # called as > julia jsoncall.jl <json_cmdfile>
io = open(jsonfile, "r") # open IOStream for read
data = read(io) # read UTF8 data from stream
close(io) # close stream
cmd = JSON3.read(String(data)) # unpack stream into [fun, farg] array
fun = Symbol(cmd[1]) # first element is Julia function name,
result = @eval $fun(cmd[2:end]...) # others are function arguments
io = open(jsonfile, "w") # open IOStream for write
write(io, JSON3.write(result)) # (over-)write result back to stream
close(io) # close stream
开放积分:
- 我第一次使用pipes/streams
- 输出格式:Julia 输出一个二元组,Matlab 创建一个 nx2 数组。
- 将 json 替换为 msgpack 以提高性能,也可能有助于类型格式化。
欢迎您提出意见!
这是一种精简的方法。如果你要改变你的函数和参数,评论服务器中的 REST 将更加灵活并且不太可能带来安全风险(因为在某些情况下你正在评估任意代码)。
#server code
using Sockets
const port = 6001
const addr = ip"127.0.0.1"
const server = listen(addr, port)
while true
try
@info "Server on $port awaiting request..."
sock = accept(server)
@info "Server connected."
msg = strip(readline(sock))
@info "got message $msg"
fstr, argstr = split(msg, limit=2)
x = parse(Float64, argstr) # or other taint checks here...
ans = eval(Meta.parse(fstr * "($x)"))
@info "server answer: $ans"
write(sock, "$ans\n")
catch y
@info "exiting on condition: $y"
end
end
# client code
using Sockets
port = 6001
server = ip"127.0.0.1"
sock = connect(server, port)
@info "Client connected to $server"
func = "sinpi"
x = 0.5
@info "starting send"
write(sock, "$func $x\n")
flush(sock)
@info "flushed send"
msg = strip(readline(sock)) # read one line of input and \n, remove \n
ans = parse(Float64, msg)
println("answer is $ans")
close(sock)
我正在寻找最简单的协议来编写远程函数调用,例如从 Matlab 到 Julia。
[out1, out2, ...] = jlcall(socket, fname, arg1, arg2, ...);
fname是一个字符串,所有其他输入和输出变量都是数值数组(或其他双方都知道的结构)在Linux,Windows作为选项。
- 客户端:打开连接、阻塞、打包和传输
- 服务器:接收、解包、处理、打包并传回
- 客户端:接收、解包、关闭连接并继续
我seen(tcp、zmq)的解决方案是用旧版本构建的,不再有效。
协议可以(应该?)限于执行 pack/transmit - receive/unpack 工作。
更新
这是我使用管道得出的结论:
function result = jlcall(varargin)
% result = jlcall('fname', arg1, arg2, ...)
% call a Julia function with arguments from Matlab
if nargin == 0 % demo
task = {'foo', 2, 3}; % demo fun, defined in jsoncall.jl
else
task = varargin;
end
% create pipe and write function and parameter(s) to pipe
pipename = tempname;
pipe = java.io.FileOutputStream(pipename);
pipe.write(uint8(jsonencode(task)));
pipe.close;
% run Julia and read result back
system(sprintf('julia jsoncall.jl %s', unixpath(pipename)))
fid = fopen(pipename, 'r');
c = fread(fid);
result = jsondecode(char(c'));
fclose(fid);
function path_unix = unixpath(path_pc)
%convert path to unix version
path_unix = path_pc;
path_unix(strfind(path_unix,'\'))='/';
# jsoncall.jl
using JSON3 # get JSON3.jl from repository first
function foo(a,b) # demo function
a+b, a*b
end
jsonfile = ARGS[1] # called as > julia jsoncall.jl <json_cmdfile>
io = open(jsonfile, "r") # open IOStream for read
data = read(io) # read UTF8 data from stream
close(io) # close stream
cmd = JSON3.read(String(data)) # unpack stream into [fun, farg] array
fun = Symbol(cmd[1]) # first element is Julia function name,
result = @eval $fun(cmd[2:end]...) # others are function arguments
io = open(jsonfile, "w") # open IOStream for write
write(io, JSON3.write(result)) # (over-)write result back to stream
close(io) # close stream
开放积分:
- 我第一次使用pipes/streams
- 输出格式:Julia 输出一个二元组,Matlab 创建一个 nx2 数组。
- 将 json 替换为 msgpack 以提高性能,也可能有助于类型格式化。
欢迎您提出意见!
这是一种精简的方法。如果你要改变你的函数和参数,评论服务器中的 REST 将更加灵活并且不太可能带来安全风险(因为在某些情况下你正在评估任意代码)。
#server code
using Sockets
const port = 6001
const addr = ip"127.0.0.1"
const server = listen(addr, port)
while true
try
@info "Server on $port awaiting request..."
sock = accept(server)
@info "Server connected."
msg = strip(readline(sock))
@info "got message $msg"
fstr, argstr = split(msg, limit=2)
x = parse(Float64, argstr) # or other taint checks here...
ans = eval(Meta.parse(fstr * "($x)"))
@info "server answer: $ans"
write(sock, "$ans\n")
catch y
@info "exiting on condition: $y"
end
end
# client code
using Sockets
port = 6001
server = ip"127.0.0.1"
sock = connect(server, port)
@info "Client connected to $server"
func = "sinpi"
x = 0.5
@info "starting send"
write(sock, "$func $x\n")
flush(sock)
@info "flushed send"
msg = strip(readline(sock)) # read one line of input and \n, remove \n
ans = parse(Float64, msg)
println("answer is $ans")
close(sock)