[R] Finding an available port for server socket
jhallman@frb.gov
jhallman at frb.gov
Thu Apr 14 23:54:54 CEST 2005
I've written a Smalltalk application which starts R on another machine and
then communicates with it via sockets. The functions involved are:
slaveStart <- function(masterHost, masterPort){
inPort <- availablePort()
sendSocket(as.character(inPort), masterHost, masterPort)
socketSlave(inPort)
}
socketSlave <- function(inPort){
## listens on inPort.
on.exit(closeAllConnections(), add = T)
repeat {
inConn <- socketConnection(port = inPort, server = T, blocking = T)
try(source(inConn, echo = T, prompt.echo = "> ",
max.deparse.length = 50000))
close(inConn)
}
}
sendSocket <- function(strings, host, port){
## open a blocking client socket, put strings on it, and close
outConn <- socketConnection(host, port, blocking = T)
writeLines(strings, outConn)
close(outConn)
}
availablePort <- function(){
## find a port that R can listen on
## just returns 40001 on Windows
portsInUse <- 0
os <- as.vector(Sys.info()["sysname"])
if(os == "Linux"){
hexTcp <- system("cat /proc/net/tcp | awk '{print $2}'", intern = T)
hexUdp <- system("cat /proc/net/udp | awk '{print $2}'", intern = T)
portsInUse <- hex2numeric(gsub(".*\:", "", c(hexTcp[-1], hexUdp[-1])))
}
if(os == "SunOS"){
## use a locally written script that massages output from netstat
portsInUse <- as.numeric(system("/mra/prod/scripts/portsInUse", intern = T))
}
port <- 40001
while(!is.na(match(port, portsInUse))) port <- port + 1
port
}
The way this works is that
(i) The Smalltalk app running on firstMachine finds an available port (say
12345) that it can listen on, start listening there, and writes
slaveStart("firstMachine", 12345)
to startUpFile.
(ii) The Smalltalk app does something like this to start R on secondMachine:
ssh secondMachine R < startUpFile > someLogFile
(iii) R sends the inPort port number back to Smalltalk.
(iv) Whenever Smalltalk wants R to do something, it opens a client connection
to inPort on secondMachine and writes R code to it. It closes the
connection when it finishes writing the R code to it. If Smalltalk
wants to get a result returned from R, the code sent will include a call
to sendSocket() to accomplish this.
(v) If Smalltalk expects a reply via sendSocket, it resumes listening on
masterPort for a connection from R.
And so on....
All of this works so far, but my availablePort() function is too ugly, and I
don't expect it to work on Windows. So my question is: Is there a better,
more portable way I can find an available port? If not, can someone put one
in there?
Jeff
More information about the R-help
mailing list