我一直在阅读套接字示例,但我只能让 JMP 确认收到请求,但我无法获取请求的有效负载或消息。有没有比套接字或调度程序更好的方法来实现非阻塞通信?
一切都在窗户上。
基本上我的工作流程是:
- 使用 JMP 呈现 HTML 页面,
- 使用 javascript、html、css 与数据交互
- 使用 Javascript XMLHTTP 请求将结果传递给 python Flask 服务器
- 通过调度程序使用 jmp 连续 ping Flask 服务器以查看 Flask 服务器是否有任何数据在等待我,如果有则 python 将返回数据并且 JMP 将获取它作为响应,如果没有则 jmp 获取字符串 '没有更新',我只是返回.
- 使用我从服务器获得的数据更新 JMP 表。
我想摆脱第 3 步和第 4 步,并使用 javascript xmlhttp 请求和 jmp 中的非阻塞侦听器直接将数据从浏览器推送到 jmp,该侦听器在接收请求时触发回调并使用该请求中的数据更新我的表。 目前我的非阻塞“监听器”是一个循环垃圾邮件调度程序。
到目前为止我读过的东西:
脚本索引:套接字
使用 JSL 从 API 获取数据的详细指南
用于从 JMP、R 和 Python 脚本获取和记录消息的套接字通信
我也不明白这个: ((blobdata == Char To Blob( "" )) & (Left(r[2], 11) == "WOULDBLOCK:" ))
r[2] 是什么? 这些东西的价值不断索引到不同的东西? 在 python 中,我会期待这样说:
r = 请求
my_dict.update({ 'last_jmp_data' :pd.DataFrame(request.json)})
这在 python 中有效以检索我的数据,但是当我尝试传回 JMP 时,唯一打印的是标头,我无法访问我发送的 JSON 数据。 我假设我的数据在一些r[#] 项目?
我正在尝试制作一些可以接收数据的非阻塞的东西,现在我正在使用一个带有调度程序的 hacky 解决方案来创建工作流并且它确实有效,但它很笨重。
我使用调度程序来安排此功能,这会触发我的烧瓶服务器,以 JSON 形式接收回数据并更新我的主表更新使 JMP 删除所有过滤器,因此我们将其记录到一个字符串中,然后重新应用它,以便用户不会失去他们正在做的事情。
我想要的是能够从 javascript 发送请求,并使用 JMP 获取它:
这是我的 JavaScript 函数,我不需要任何回复,我只希望它转到 JMP。 以前我使用不同的 JavaScript 解决方法将 JSON 文件写入我的下载,并使用我的调度程序循环来观察用户下载文件夹中的特定 JSON 文件以更新表。
此应用程序是在用户 PC 上本地运行的单用户应用程序,不与任何外部资源通信,我只需要在浏览器中进行 GUI/某些数据交互,但我仍想将该数据返回到 JMP我的嵌合 JMP/HTML/JS/CSS 应用程序。
我用来将数据从浏览器发送到我的 python 服务器的 Javascript 代码,我想直接将其发送到 JMP 并在它到达时进行更新。
var xhr = new XMLHttpRequest();
xhr.open("POST", 'http://localhost:8081', true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send([my_json_data]);
跳转调度程序循环
//scheduled loop to ping python local server and see if it's time to update:
get_remote_update = Function({},
s = Schedule(.25,
//show("remote update fn");
//check_downloads_folder(); // old routine that was watching download folder
check_downloads_over_ip();
get_remote_update(); //loops by scheduling the event again
);对 python 服务器的 jmp 调用接收 JSON 数据并在需要时更新。
//****************************************************************
//check_downloads_OVER_IP();
//****************************************************************
// EXPLORE THIS dt = Open( Char To Blob( request << Send() ), "JSON" );
// see if we can just get the response back into a table without creating it with the weird JMP thing
check_downloads_over_ip = Function({},
request = New HTTP Request(
URL("localhost:8088/get_update"),
Method("Post"),
Timeout( .5 ),
);
data=request << Send;
if((data != "No Update" > 0) & ( isempty(data) != 1 ),
obj = JSON:Parse( data );
dt = JSON:Make Table(obj);
dt << show window(0);
temp_dtf = CHAR(dtf <<GET script=""></GET>
套接字脚本我特别不明白这一部分: //将收到的任何内容写入日志
它在日志中打印标头,但我无法访问我发送的 JSON 数据。
Names default to here( 1 );
//Table to hold received data
dtLog = New Table( "Log",
New Column( "Time", Numeric, "Continuous", Format( "m/d/y h:m:s", 23, 0 ),
Input Format( "m/d/y h:m:s", 0 ) ),
New Column( "Client", Character, "Nominal" ),
New Column( "Message", Character, "Nominal" )
);
//Wait for and get data from remote machine
receivedata = Function( {c, waittime = 1, waitcount = 10},
//Varaible to store data received from remote machine
blobdata = Char To Blob( "" );
//Make socket is connected
r = c << GetPeerName();
//While receiving data or waiting to receive data
i = 0;
While(
(
(r[2] == "ok") |
((blobdata == Char To Blob( "" )) & (Left(r[2], 11) == "WOULDBLOCK:" ))
) &
(i < waitcount),
i++;
//Get data
r = c << recv( 100000 );
//If no data is received yet, wait
If(Left(r[2], 11) == "WOULDBLOCK:", Wait( waittime ) );
//Write whatever is received to the log
show("writing to log now");
Write( Blob to Char( r[3] ) );
show("Done writing to log now");
//join data to whatever is already received
blobdata = blobdata || r[3];
);
return( blobdata );
);
//Get log info from remote machine, store it in a data table
processlogconnection = function( {c},
//New row in log table
dtLog << Add Rows( 1 );
rowout = N Rows( dtLog );
Column( dtLog, "Time" )[rowout] = Today();
//Get computer name of remote machine
r = c << GetPeerName();
Column( dtLog, "Client" )[rowout] = r[3];
//Get message from the remote machine
Column( dtLog, "Message" )[rowout] = Blob to Char( receivedata( c ) );
//Close the connection
c << Close;
);
//Function to accept conections from remote machine, calls another
//function to handle communication with that machine
callbackfn = function( {x},
//Call another function with the connection returned from the Accept message
If( x[2] == "ok", processlogconnection( x[4] ) );
);
//Create a socket
con = Socket();
//Use a specific port on this computer
con << Bind( "localhost", "8081" );
//Tell this socket to be ready for other sockets to connect to it
Write( "\!nlistening on ", (con << getSockName)[3]);
con << Listen();
//Verify that the connection is active
con << getsockname;
//When something connects to this socket, call a function to handle
//the connection. Accept connections for the next 5 minutes.
con << Accept(callbackfn, 30000);
//Now messages can be sent to this connection.
//When all done, close the connection
//con << close();
您可以使用 JMP 的 HTTP 请求来 ping Flask 服务器。 这将消除您想要做的事情的复杂程度。
您可以使用 HTTP 请求查询服务器(我假设是 GET 操作)并直接使用返回读取响应(如 JSON 有效负载),然后在准备就绪时再次使用 HTTP 请求(可能作为 GET)并处理来自服务器。 当然,如果您使用的是套接字而不是 HTTP/HTTPS,那么您会希望坚持使用套接字方法。
此外,JMP 的套接字不支持 https,仅支持 http。 它们是低级套接字代码的相当薄的包装器,对 http 协议一无所知:你必须自己构建它。 脚本索引中有一个完整的示例:
The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.The "listen" example is self-contained.“听”示例是独立的。
用 JSL 构建 Web 服务器是相当困难的。 如果您已经在使用 JMP 中的 Python,请查看果冻视频的项目文件特别是 NumberServer。 我需要运行 JMP 的多个副本来生成视频中的图像,我需要一种方法来将他们需要完成的工作交给他们。 数字服务器完成了这项工作,并为 JSL 仪表板提供了工具,这样我就可以知道什么时候需要注意。 (我认为 python 服务器是单线程的,事实证明这对于为同时请求提供唯一编号是一件好事。 至少我从来没有注意到重复...)
这听起来很有希望 javascript 也可以在本地制作 websockets。
运行程序能否以非阻塞方式将数据导入 JMP? 我想当你有外部程序运行你的 JMP gui 时会被阻止吗?
从那个页面:
Note: If you use Run Program() to launch a GUI program, JMP is inoperable until you close the program
编辑:我实际上已经下载了这个并尝试理解它一次! 我再试一次。
这不是我目前正在做的吗?
我只对套接字感兴趣,因为它似乎是一种创建非阻塞侦听器的方法,而我目前的机制是每半秒将 HTTP GET 请求从 JMP 流式传输到 Flask,以查看 Web 浏览器内容是否因用户交互而改变。 我希望将一个事件从 flask 或 javascript 推送到 JMP,而不需要 JMP 自己提出任何要求。
check_downloads_over_ip() 函数 //http 获取
和 get_remote_update()。 // 调度器循环
get_remote_update() 使 check_downloads 函数在调度程序中不断调度,作为使其“实时”的机制
问题是调度程序不是生成非阻塞行为的非常优雅的方式。
我希望 JMP 坐下来听(以非阻塞方式),然后我可以将来自 javascript 的 http 请求直接在浏览器中推送到 JMP 并完全消除烧瓶服务器。
关键是 JMP 具有从服务器提取数据然后处理响应的工具,但是我可以在 JMp 不首先请求任何内容的情况下将事件从浏览器或服务器推送到 JMP 中吗?
我将从我的应用程序中剥离所有 IP 并发布视频以更清楚地说明我要做什么。
RunProgram 可以并发异步运行 N 个外部程序。 如果 JMP 处于空闲状态,则 N RunPrograms 可以在接收到 stdin 上的数据时运行它们的 ReadFunction() 脚本,并且它们可以通过 stdout 写入数据。 如果Python是RunProgram正在执行的程序,Python的stdin就是RunProgram的stdout,...stdout...stdin。 (N 可能不会大于几十个。)
RunProgram 可以运行 excel 之类的东西,但会阻塞。 RunProgram 对于带有 stdin 和 stdout 的命令行程序要好得多。 您可能会使用 cmd.exe,或者您可能会使用链接在远程 Linux 机器上打开 shell。 或者您可以运行您自己的 C 或 Python 或其他语言程序。
RunProgram 有两种操作模式:如果它有 ReadFunction("text") 则它以阻塞模式运行,收集所有标准输出并返回一个字符串。 否则它以非阻塞模式运行并返回一个 RunProgram 对象你必须保留在一个变量中(否则它将在过程完成之前被删除。)
您只能向 RunProgram 对象发送一些命令;你可以询问连接和发送和接收数据。
我通常不会将调度程序用于此类事情,因为它想要打开一个窗口,但是请看动态消息. 同一篇文章展示了如何使用 CMD 启动命令运行 msedge 浏览器而没有阻塞行为。
我已经用 JSL 编写了服务器(同一篇文章),但我认为使用 python 或 python+flask 解决方案要好得多。 如果你使用 flask,试试这个:让 RunProgram 启动 Python+flask 代码,并在它的 readfunction 和 writefunction 中给 RunProgram 一些逻辑来与 python 代码(stdin/stdout)通信。 在 python 代码中,添加一个线程来与 JMP 对话。 Flask 服务器有自己的线程来处理 http 请求。 如果服务器需要向 jmp 推送一些内容,它需要向 JMP 线程发送一个事件信号,该线程将向 JMP 打印一些内容。 您可能需要另一个 Python 线程,它是一个读取器线程,用于侦听 JMP。