Manchmal ist es hilfreich, Nachrichten oder Daten von Skripts mit langer Laufzeit oder Skripts, die auf Remotecomputern ausgeführt werden, an einem zentralen Ort zu sammeln.Im Anhang sind vier Dateien, die dies demonstrieren:
- Ein „Server“, der Nachrichten von anderen Maschinen oder Prozessen sammelt und sie in eine Datentabelle einfügt. Führen Sie dies in einer von anderen Skripten oder Tabellen getrennten Instanz von JMP aus.
- Ein 'Client'-JSL-Skript, das Nachrichten an den Server sendet, betten Sie dies in Skripte ein.
- Ein „Client“-R-Skript, das Nachrichten an den Server sendet
- Ein „Client“-Python-Skript, das Nachrichten an den Server sendet
Hier ist ein Beispiel dafür, wie dies aussehen könnte: Die Clients auf der rechten Seite können sich auf verschiedenen Computern oder separate Kopien von JMP auf demselben Computer befinden.

Der wichtige Code sieht so aus:
Server
//Create a socket
con = Socket();
//Use a specific address and port on this computer
con << Bind( "10.0.0.2", "12345" );
//Tell this socket to be ready for other sockets to connect to it
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, 300);
//Now messages can be sent to this connection.
//When all done, close the connection
con << close();
Wobei die Callback-Funktion etwa so aussehen würde (die eigentliche Funktion ist komplexer, siehe unten):
//Simplified function to handle communication with the client, do not use as is
callbackfn = function( {x},
If( x[2] == "ok",
//Get data
r = x[4] << recv( 1000 );
//While data was received
While( r[2] == "ok",
//Write it to the log
write( Blob to Char( r[3] ) );
//try to get more data
r = x[4] << recv( 1000 );
);
);
//close the connection to the client
x[4] << Close;
);
Hier ist eine etwas komplexere Callback-Funktion, die das Blockieren behandelt (häufig):
Mehr sehen...
Hier ist ein Beispiel für einen vollständigen Servercode:
Mehr sehen...
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
Write( Blob to Char( r[3] ) );
//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( "10.0.0.2", "12345" );
//Tell this socket to be ready for other sockets to connect to it
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, 300);
//Now messages can be sent to this connection.
//When all done, close the connection
con << close();
Namen sind standardmäßig hier ( 1 ); //Tabelle zum Halten der empfangenen Daten dtLog = New Table( "Log", New Column( "Time", Numeric, "Continuous", Format( "m/d/yh:m:s", 23, 0 ), Input Format ( "m/d/yh:m:s", 0 ) ), Neue Spalte( "Kunde", Zeichen, "Nominal" ), Neue Spalte( "Nachricht", Zeichen, "Nominal" ) ); //Warten und Abrufen von Daten vom Remote-Rechner Receivedata = Function( {c, waittime = 1, Waitcount = 10}, //Variable zum Speichern der vom Remote-Rechner empfangenen Daten blobdata = Char To Blob( "" ); //Socket erstellen ist verbunden r = c << GetPeerName(); //Während Datenempfang oder Warten auf Datenempfang 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 Daten wurden noch empfangen, warten If(Left(r[2], 11) == "WOULDBLOCK:", Wait( waittime ) ); //Was auch immer empfangen wird in das Protokoll schreiben Write( Blob to Char( r[3] ) ); // Daten mit dem verbinden, was bereits empfangen wurde blobdata = blobdata || r[3]; ); return( blobdata ); ); //Protokollinformationen vom entfernten Rechner abrufen, in einer Datentabelle speichern processlogconnection = function( {c}, //Neue Zeile in der Protokolltabelle dtLog << Zeilen hinzufügen( 1 ); rowout = N Zeilen( dtLog ); Spalte( dtLog , "Time" )[rowout] = Today(); //Computernamen des entfernten Rechners abrufen r = c << GetPeerName(); Column( dtLog, "Client" )[rowout] = r[3]; //Get Nachricht vom entfernten Rechner Column(dtLog, "Message" )[rowout] = Blob to Char(receivedata(c)); //Schließe die Verbindung c << Close; ); //Funktion zum Akzeptieren von Verbindungen von der entfernten Maschine, ruft eine andere //Funktion auf, um die Kommunikation mit dieser Maschine abzuwickeln callbackfn = function( {x}, //Aufruf einer anderen Funktion mit der Verbindung, die von der Accept-Nachricht zurückgegeben wird If( x[2] == "ok", processlogconnection( x[4] ) ); ); //Socket erstellen con = Socket(); //Verwenden Sie einen bestimmten Port auf diesem Computer con << Bind( "10.0.0.2", "12345" ); // Diesem Socket mitteilen, dass er für andere Sockets bereit sein soll, um sich mit ihm zu verbinden con << Listen (); //Überprüfen Sie, ob die Verbindung aktiv ist con << getsockname; //Wenn sich etwas mit diesem Socket verbindet, rufe eine Funktion auf, //um die Verbindung zu handhaben. Akzeptieren Sie Verbindungen für die nächsten 5 Minuten. con << Accept(callbackfn, 300); //Jetzt können Nachrichten an diese Verbindung gesendet werden. //Wenn alles fertig ist, schließe die Verbindung con << close();
JSL-Client
Names default to here( 1 );
//function to send a message to a waiting connection
SendMessage = Function( {message},
//Create a socket
con = Socket();
//Connect to a socket that is already bound to, listening on, and accepting
//connections on a port. This is the server IP address, not the client.
con << Connect( "10.0.0.2", "12345" );
//Send data
r = con << Send( Char To Blob( message ) );
///check that the data was sent
if(r[2] == "ok", result = "sent", result = "fail" );
//close the connection
con << Close;
return( result );
);
//send messages
Write( SendMessage( "Hi" ) );
R-Client
sendmessage = function( message ) {
con <- socketConnection(host="10.0.0.2", port = 12345, blocking=FALSE,
server=FALSE, open="r+")
write_resp <- write(message, con)
close(con)
}
sendmessage("Hi from R")
Python-Client
import socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(("10.0.0.2", 12345))
client_socket.send("Hello from Python")
client_socket.close()
break;
Powershell-Client
$socket = new-object System.Net.Sockets.TcpClient( "10.0.0.2", 12345)
$stream = $socket.GetStream()
$writer = new-object System.IO.StreamWriter $stream
$writer.WriteLine( "Hello from Powershell`n" )
$writer.Flush()
$writer.Close()
Dies soll eher eine Einführung in die Socket-Kommunikation für alle sein, die nach Beispielcode suchen, als nach einem funktionalen Protokollierungsmechanismus, aber ich freue mich über Ihre Kommentare und Vorschläge!