远程函数调用最简单的网络协议?

Most simple network protocol for a remote function call?

我正在寻找最简单的协议来编写远程函数调用,例如从 Matlab 到 Julia。

[out1, out2, ...] = jlcall(socket, fname, arg1, arg2, ...);

fname是一个字符串,所有其他输入和输出变量都是数值数组(或其他双方都知道的结构)在Linux,Windows作为选项。

  1. 客户端:打开连接、阻塞、打包和传输
  2. 服务器:接收、解包、处理、打包并传回
  3. 客户端:接收、解包、关闭连接并继续

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

开放积分:

欢迎您提出意见!

这是一种精简的方法。如果你要改变你的函数和参数,评论服务器中的 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)