我一直在閱讀套接字示例,但我可以讓 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.“聽”示例是獨立的。
用 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 可以在接收標準輸入數據時運行它們的 ReadFunction() 腳本,並且它們可以通過標準輸出寫入數據。 如果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。