HenrikBengtsson / Wishlist-for-R

Features and tweaks to R that I and others would love to see - feel free to add yours!
https://github.com/HenrikBengtsson/Wishlist-for-R/issues
GNU Lesser General Public License v3.0
134 stars 4 forks source link

WISH: Make serverSocket(0) useful (+ find a random TCP port that can be listened to) #158

Open HenrikBengtsson opened 10 months ago

HenrikBengtsson commented 10 months ago

In many situations, it's useful to be able to identify a "free" TCP port, i.e. a port that we can bind to.

CORRECTION +30 min: serverSocket() would only validate that we can listen to the port. To assert we can bind to it, we would have to do more. I need :coffee:

In R (>= 4.0.0), we can almost use serverSocket(0) for this. It will open a servsockconn connection on a random TCP port assigned to us by the operating system. This works on Linux, macOS, and MS Windows. For example,

> con <- serverSocket(port = 0L)

> print(con)
A connection with                          
description "localhost"   
class       "servsockconn"
mode        "a+"          
text        "text"        
opened      "opened"      
can read    "yes"         
can write   "yes"  

> str(con)
 'servsockconn' int 3
 - attr(*, "conn_id")=<externalptr> 

However, this is currently a useless connection, because we do not know which port is used here.

Wish

This would make it possible to use the above servsockconn connection as-is, but it would also make it possible to find a random available TCP port, e.g.

find_available_tcp_port <- function() {
  con <- serverSocket(port = 0L)
  on.exit(close(con))
  port(con)
}

References

cc/ @noamross

shikokuchuo commented 8 months ago

You can do this already using the equivalent in {nanonext}, but agree it would be nice for base R to have this.

find_available_tcp_port <- function() {
  s <- nanonext::socket(listen = "tcp://127.0.0.1:0")
  on.exit(close(s))
  nanonext::opt(s$listener[[1L]], "tcp-bound-port")
}