[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