DotNet:SocketException (111):Debian 上的 UDP 连接被拒绝
DotNet: SocketException (111): Connection refused for UDP on Debian
我遇到了一个奇怪的问题;我有两个应用程序,一个前端和一个后端。前端使用 UDP 向后端发送消息。我有使用 UDP 的特定原因,但其中之一是我不在乎后端何时因某种原因关闭或无法访问。我只是想让消息丢失。是的,你没有看错
现在忘掉后端吧。让我们假设后端未启动,但前端无论如何都会向后端发送一个 UDP 数据包。客户端发送永远不会到达的消息,在 Windows 上就好了。如预期。在 Linux(确切地说是 Debian)上,我得到了 SocketException (111): Connection refused
。当我将消息发送到(不存在的)远程主机时,不会发生这种情况。但是,一旦主机为 localhost
或 127.0.0.1
甚至 192.168.1.1
(机器的 LAN IP),就会抛出异常。当主机是 8.8.8.8
或 192.168.1.10
(我局域网中的某个随机主机)或 192.168.1.200
(我局域网中不存在的主机)时,例外情况是 not 抛出。
因为我觉得我快疯了所以我用其他语言测试了它,它们似乎都表现正确(即发送消息(永远不会到达),没有例外)。
这是有效的,全部在同一台 Debian 10 机器上:
Python:
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
while True:
sock.sendto(b"Hello, World!", ("127.0.0.1", 12345))
print(".", end = '')
PHP:
<?php
$sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
$msg = "Hello world!";
$len = strlen($msg);
while (true) {
socket_sendto($sock, $msg, $len, 0, '127.0.0.1', 12345);
echo '.';
}
Perl:
use Socket;
socket(SOCKET, PF_INET, SOCK_DGRAM, getprotobyname("udp")) or die "socket: $!";
$MSG = "Hello world!";
$endpoint = sockaddr_in(12345, inet_aton("127.0.0.1"));
while(true) {
send(SOCKET, $MSG, 0, $endpoint) == length($MSG) or die "cannot send: $!";
print(".");
}
对于上述所有三个脚本,输出为(如预期):.............…
等
现在是 .Net (C#) 版本(我开始时是异步的,但在我的搜索中我什至回到了同步):
C# 同步:
static void Main(string[] args)
{
var data = Encoding.UTF8.GetBytes("Hello world");
var client = new UdpClient("127.0.0.1", 12345);
while (true) {
client.Send(data, data.Length);
Console.Write(".");
}
}
C# 异步:
static async Task Main(string[] args)
{
var data = Encoding.UTF8.GetBytes("Hello world");
var client = new UdpClient("127.0.0.1", 12345);
while (true) {
await client.SendAsync(data, data.Length).ConfigureAwait(false);
Console.Write(".");
}
}
我什至将代码重写为 而不是 使用 UdpClient
而 Socket
;同样的结果。 .Net 不断抛出 SocketException (111): Connection refused
.
我唯一发现 可能 相关的是 this over at PerlMonks:
Snippet from socket man page SOCKET OPTIONS section for option SO_BSDCOMPAT:
If enabled ICMP errors received for a UDP socket will not be passed to the user program. In later kernel versions, support for this option has been phased out: Linux 2.4 silently ignores it, and Linux 2.6 generates a kernel warning (printk()) if a program uses this option.
但是因为我无法设置任何标志,甚至远程类似于 SO_BSDCOMPAT
,这似乎是一个死胡同(而且可能根本不是问题)。
有人任何线索知道这里发生了什么吗?
总结:当没有“后端”(或服务器)侦听时,C# 以上在 Windows 上运行良好;消息只是丢失 - 正如预期的那样。在 Linux(Debian 10)上,C# 代码抛出异常,但 Python、Perl 和 PHP 似乎工作正常,排除了 OS(恕我直言)。我是 运行 dotnet 5.0.202
、Windows 10 和 Debian 10(Linux myhost 4.19.0-13-amd64 #1 SMP Debian 4.19.160-2 (2020-11-28) x86_64 GNU/Linux)
- 都是最新的。
好吧,你一定是在开玩笑...正如我所说:
I even rewrote the code to not use a UdpClient
but a Socket
...但我在套接字上使用了 .Send()
和 .SendAsync()
方法。我刚刚尝试使用 .SendTo()
和 .SendToAsync()
方法,这似乎有效。哪个...有点有意义,因为要使 .Send()
和 .SendAsync()
方法起作用,您需要先调用 .Connect()
并且 .SendTo()
/.SendToAsync()
允许您在 SendTo...
调用本身中指定远程端点。
static void Main(string[] args)
{
var data = Encoding.UTF8.GetBytes("Hello world");
var socket = new Socket(SocketType.Dgram, ProtocolType.Udp);
var ep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 12345);
while (true) {
socket.SendTo(data, ep);
Console.Write(".");
}
}
所以这可以/将被标记为已解决。
我遇到了一个奇怪的问题;我有两个应用程序,一个前端和一个后端。前端使用 UDP 向后端发送消息。我有使用 UDP 的特定原因,但其中之一是我不在乎后端何时因某种原因关闭或无法访问。我只是想让消息丢失。是的,你没有看错
现在忘掉后端吧。让我们假设后端未启动,但前端无论如何都会向后端发送一个 UDP 数据包。客户端发送永远不会到达的消息,在 Windows 上就好了。如预期。在 Linux(确切地说是 Debian)上,我得到了 SocketException (111): Connection refused
。当我将消息发送到(不存在的)远程主机时,不会发生这种情况。但是,一旦主机为 localhost
或 127.0.0.1
甚至 192.168.1.1
(机器的 LAN IP),就会抛出异常。当主机是 8.8.8.8
或 192.168.1.10
(我局域网中的某个随机主机)或 192.168.1.200
(我局域网中不存在的主机)时,例外情况是 not 抛出。
因为我觉得我快疯了所以我用其他语言测试了它,它们似乎都表现正确(即发送消息(永远不会到达),没有例外)。
这是有效的,全部在同一台 Debian 10 机器上:
Python:
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
while True:
sock.sendto(b"Hello, World!", ("127.0.0.1", 12345))
print(".", end = '')
PHP:
<?php
$sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
$msg = "Hello world!";
$len = strlen($msg);
while (true) {
socket_sendto($sock, $msg, $len, 0, '127.0.0.1', 12345);
echo '.';
}
Perl:
use Socket;
socket(SOCKET, PF_INET, SOCK_DGRAM, getprotobyname("udp")) or die "socket: $!";
$MSG = "Hello world!";
$endpoint = sockaddr_in(12345, inet_aton("127.0.0.1"));
while(true) {
send(SOCKET, $MSG, 0, $endpoint) == length($MSG) or die "cannot send: $!";
print(".");
}
对于上述所有三个脚本,输出为(如预期):.............…
等
现在是 .Net (C#) 版本(我开始时是异步的,但在我的搜索中我什至回到了同步):
C# 同步:
static void Main(string[] args)
{
var data = Encoding.UTF8.GetBytes("Hello world");
var client = new UdpClient("127.0.0.1", 12345);
while (true) {
client.Send(data, data.Length);
Console.Write(".");
}
}
C# 异步:
static async Task Main(string[] args)
{
var data = Encoding.UTF8.GetBytes("Hello world");
var client = new UdpClient("127.0.0.1", 12345);
while (true) {
await client.SendAsync(data, data.Length).ConfigureAwait(false);
Console.Write(".");
}
}
我什至将代码重写为 而不是 使用 UdpClient
而 Socket
;同样的结果。 .Net 不断抛出 SocketException (111): Connection refused
.
我唯一发现 可能 相关的是 this over at PerlMonks:
Snippet from socket man page SOCKET OPTIONS section for option SO_BSDCOMPAT:
If enabled ICMP errors received for a UDP socket will not be passed to the user program. In later kernel versions, support for this option has been phased out: Linux 2.4 silently ignores it, and Linux 2.6 generates a kernel warning (printk()) if a program uses this option.
但是因为我无法设置任何标志,甚至远程类似于 SO_BSDCOMPAT
,这似乎是一个死胡同(而且可能根本不是问题)。
有人任何线索知道这里发生了什么吗?
总结:当没有“后端”(或服务器)侦听时,C# 以上在 Windows 上运行良好;消息只是丢失 - 正如预期的那样。在 Linux(Debian 10)上,C# 代码抛出异常,但 Python、Perl 和 PHP 似乎工作正常,排除了 OS(恕我直言)。我是 运行 dotnet 5.0.202
、Windows 10 和 Debian 10(Linux myhost 4.19.0-13-amd64 #1 SMP Debian 4.19.160-2 (2020-11-28) x86_64 GNU/Linux)
- 都是最新的。
好吧,你一定是在开玩笑...正如我所说:
I even rewrote the code to not use a
UdpClient
but aSocket
...但我在套接字上使用了 .Send()
和 .SendAsync()
方法。我刚刚尝试使用 .SendTo()
和 .SendToAsync()
方法,这似乎有效。哪个...有点有意义,因为要使 .Send()
和 .SendAsync()
方法起作用,您需要先调用 .Connect()
并且 .SendTo()
/.SendToAsync()
允许您在 SendTo...
调用本身中指定远程端点。
static void Main(string[] args)
{
var data = Encoding.UTF8.GetBytes("Hello world");
var socket = new Socket(SocketType.Dgram, ProtocolType.Udp);
var ep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 12345);
while (true) {
socket.SendTo(data, ep);
Console.Write(".");
}
}
所以这可以/将被标记为已解决。