Van*_*man 14 r localhost loopback-address
考虑以下R脚本:
con <- socketConnection(host = "localhost", port = 8, server = TRUE, blocking = TRUE, open = "a+b")
close(con = con)
Run Code Online (Sandbox Code Playgroud)
将这些行保存为.R文件,然后从命令行运行它会产生(在Windows上)防火墙警告.至少,如果在第一次出现的"高级安全Windows防火墙"下没有R规则.我被告知在Mac上发生同样的情况,但我自己也无法验证.如何更改以允许localhost环回但避免弹出窗口?
上下文:我为使用并行处理的人(在一台本地机器上)编写了一些代码.然而,这个警告突然出现在他们的屏幕上,他们开始怀疑.愚蠢的是,即使人们点击否或忽略弹出窗口,并行处理似乎仍然有效.我认为这是一个迹象,表明可以修改此代码,以便不提供此弹出窗口并仍然可以正常运行.
我已经看到了在其他语言非常类似的问题(1,2,3),我想知道是否有可能做R.相同
Tec*_*e01 10
我的感觉是,导航此问题的最简单方法是在应用程序安装过程中添加防火墙规则.
我在下面提供了一个示例脚本,我希望这有助于指明您正确的方向.
netsh advfirewall firewall add rule name="RScript" action=allow program="C:\Program Files\Microsoft\R Client\R_SERVER\bin\x64\Rscript.exe" enable=yes Localip="127.0.0.1" localport="9999" protocol=tcp interfacetype=any profile=private dir=in
Run Code Online (Sandbox Code Playgroud)
PS <hidden>\dev\stackoverflow\47353848> netsh advfirewall firewall add rule name="RScript" action=allow program="C
:\Program Files\Microsoft\R Client\R_SERVER\bin\x64\Rscript.exe" enable=yes Localip="127.0.0.1" localport="9999" protoco
l=tcp interfacetype=any profile=private dir=in
Ok.
Run Code Online (Sandbox Code Playgroud)
假设您使用RScript运行R文件,上述netsh脚本将使RScript应用程序能够使用专用网络上的TCP访问端口9999上的环回地址127.0.0.1.从这一点开始,您不应该获得防火墙提示.
c:\<hidden>\dev\stackoverflow\47353848> Rscript.exe .\server.R
Listening...
Run Code Online (Sandbox Code Playgroud)
为什么这样?好吧,据我所知base::socketConnection,即使使用环回连接器,也无法在不触发Windows Defender防火墙提示的情况下在Windows上使用R.有趣的是,如果您使用Java,则不会收到提示.我看了两个实现,但无法确定原因
server <- function() {
while (TRUE) {
writeLines("Listening...")
con <- socketConnection(host = "loopback",
port = 9999,
server = TRUE,
blocking = TRUE,
timeout = 0,
open = "r+")
data <- readLines(con, 1)
print(data)
response <- toupper(data)
writeLines(response, con)
close(con)
}
}
server()
Run Code Online (Sandbox Code Playgroud)
client <- function() {
while (TRUE) {
con <- socketConnection(host = "loopback",
port = 9999,
server = FALSE,
blocking = TRUE,
open = "r+")
f <- file("stdin")
open(f)
print("Enter text to be upper-cased, q to quit")
sendme <- readLines(f, n = 1)
if (tolower(sendme) == "q") {
break
}
write_resp <- writeLines(sendme, con)
server_resp <- readLines(con, 1)
print(paste("Your upper cased text: ", server_resp))
close(con)
}
}
client()
Run Code Online (Sandbox Code Playgroud)
(对于我对防火墙规则的看法,请参见最后)
该功能似乎根本不存在。
在 C 中,您使用socket,bind和listen调用创建服务器套接字,并通过调用获取传入连接accept。src\modules\internet\sock.c 是socket handler代码,它有打开socket、Sock_connect打开和连接socket两个函数,所以这个是客户端用的,int Sock_open(Sock_port_t port, Sock_error_t perr)是打开服务端socket的(和实际的接电话是在Sock_listen)。问题是这Sock_open只有一个port参数,并且主机/接口是硬编码的:
/* open a socket for listening */
int Sock_open(Sock_port_t port, Sock_error_t perr)
{
int sock;
struct sockaddr_in server;
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
return Sock_error(perr, errno, 0);
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons((short)port);
if ((bind(sock, (struct sockaddr *)&server, sizeof(server)) < 0) ||
(listen(sock, MAXBACKLOG) < 0)) {
close(sock);
return Sock_error(perr, errno, 0);
}
return sock;
}
Run Code Online (Sandbox Code Playgroud)
它绑定并侦听 INADDR_ANY,这意味着您 PC 的所有接口(不仅仅是环回),并且它肯定会触发防火墙。
该函数是从相邻的 Rsock.c 调用的,仍然使用单个端口参数,而其他一切都丢失的地方似乎提前了一步,在 sockconn.c 中:
static Rboolean sock_open(Rconnection con)
{
Rsockconn this = (Rsockconn)con->private;
int sock, sock1, mlen;
int timeout = this->timeout;
char buf[256];
if(timeout == NA_INTEGER || timeout <= 0) timeout = 60;
this->pend = this->pstart = this->inbuf;
if(this->server) {
sock1 = R_SockOpen(this->port);
Run Code Online (Sandbox Code Playgroud)
最后一行是 RSockconn 的主机部分被忽略的地方,尽管它包含这样的字段:
/* used in internet module */
typedef struct sockconn {
int port;
int server;
int fd;
int timeout;
char *host;
char inbuf[4096], *pstart, *pend;
} *Rsockconn;
Run Code Online (Sandbox Code Playgroud)
(这是在外部定义的,在 src\include\Rconnections.h 中)
不幸的是,这不能解决您的问题,这就是您遇到问题的原因。您可以考虑为 R 的开发人员提交错误报告。 评论表明他们从远古时代获得了网络代码,当时防火墙和互联网安全不像现在那么受关注:
/* Simple sockets interface derived from the sockets UICI
implementation in Appendix B of Practical UNIX Programming,
K. A. Robbins and S. Robbins, Prentice Hall, 1996. */
Run Code Online (Sandbox Code Playgroud)
这很好,只是 21 年前。
netsh advfirewall firewall add rule name="Rtest" dir=in action=block program="<location and name of your executable>"
Run Code Online (Sandbox Code Playgroud)
就是这样。问题是环回接口根本没有防火墙(因此与 127.0.0.1 的连接始终有效 - 我也测试了它,只是为了安全起见),并且您不希望其他任何人访问您的程序。我在其他答案中看到了 'allow'-s,而您不希望那样。根据其他用途,您可能必须使用“localport=8”和/或“protocol=tcp”来限制规则,但块部分是肯定的。
您基本上被迫使用Windows防火墙,因为它随Windows一起提供.因此,可能在.R文件中包含一个.bat文件,该文件会创建异常并告诉用户运行它?或者也许用IExpress制作一个.exe安装程序?这可能会成功.我会建议.exe安装程序路由,因为.bat文件似乎有点可疑,因为非技术精湛的用户会在它要求管理员权限时会哭狼.如果您更愿意使用.bat文件路由,netsh命令可以为任何程序创建防火墙例外.
这个通过使用dir = out开关接受传出连接,并通过action = allow开关启用异常
netsh advfirewall firewall add rule name="PROGRAM_NAME" dir=out action=allow program="C:\PROGRAMPATH" enable=yes
Run Code Online (Sandbox Code Playgroud)
这个通过使用dir = in开关接受传入连接,并通过action = allow开关启用异常
netsh advfirewall firewall add rule name="PROGRAM_NAME" dir=out action=allow program="C:\PROGRAMPATH" enable=yes
Run Code Online (Sandbox Code Playgroud)
嘿,祝你好运!希望它适合你,萌芽,希望我的建议有所帮助.
如何将规则添加到Windows防火墙 - DigitalCitizen
使用PSOCK群集的另一种方法是使用callr在后台运行多个R会话.该future.callr包(*)提供了并行后端未来框架(免责声明:我是作者).它允许您并行化所有操作系统,包括Windows,而无需通过套接字(因此没有防火墙).例:
library("future")
plan(future.callr::callr)
y <- future_lapply(x, FUN = my_fcn_in_parallel)
Run Code Online (Sandbox Code Playgroud)
library("doFuture")
plan(future.callr::callr)
registerDoFuture()
y <- foreach(i in seq_along(x)) %dopar% my_fcn_in_parallel(x[[i]])
Run Code Online (Sandbox Code Playgroud)
仅供参考,对于PSOCK群集,请使用plan(multisession).
(*)future.callr在2018-02-13的CRAN 上将在其依赖的开发者版本的呼叫者提交给CRAN后立即提交给CRAN.