当创建一个HttpListener
对象使用
var server = new HttpListener();
server.Prefixes.Add("http://*:8080/");
server.Start();
一切正常。但是,当我使用
var server = new HttpListener();
server.Prefixes.Add("http://demindiro.com:8080/");
server.Start();
它抛出System.Net.Sockets.SocketException (0x80004005): The requested address is not valid in this context
(下面是完整的堆栈跟踪)。
在谷歌上搜索异常后,很明显它与所使用的地址有关。深入挖掘后Mono源代码Http监听器 https://github.com/mono/mono/blob/master/mcs/class/System/System.Net/HttpListener.cs and 端点管理器 https://github.com/mono/mono/blob/master/mcs/class/System/System.Net/EndPointManager.cs我确定问题可能出在这部分代码中(位于获取EP监听器 https://github.com/mono/mono/blob/7e7d8a3b4fccfaca91ef74b963f495c704e07085/mcs/class/System/System.Net/EndPointManager.cs#L80-L97):
static EndPointListener GetEPListener (string host, int port, HttpListener listener, bool secure)
{
IPAddress addr;
if (host == "*")
addr = IPAddress.Any;
else if (IPAddress.TryParse(host, out addr) == false){
try {
#pragma warning disable 618
IPHostEntry iphost = Dns.GetHostByName(host);
#pragma warning restore 618
if (iphost != null)
addr = iphost.AddressList[0]; // <---
else
addr = IPAddress.Any;
} catch {
addr = IPAddress.Any;
}
// ...
}
我发现几乎在所有情况下ÌPAddress.Any
除非它可以将外部 IP 地址与给定的主机名关联起来,否则会使用它。
然而,我只能假设这是故意的,因为它是相当明确地写的,而且看起来HttpListener
对于其他开发人员来说工作得很好,所以在这一点上,我对这里出了什么问题一无所知。
Stacktrace:
Unhandled Exception:
System.Net.Sockets.SocketException (0x80004005): The requested address is not valid in this context
at System.Net.Sockets.Socket.Bind (System.Net.EndPoint localEP) [0x00043] in <50d80b08c1a5449282b22aedf03ce925>:0
at System.Net.EndPointListener..ctor (System.Net.HttpListener listener, System.Net.IPAddress addr, System.Int32 port, System.Boolean secure) [0x00047] in <50d80b08c1a5449282b22aedf03ce925>:0
at System.Net.EndPointManager.GetEPListener (System.String host, System.Int32 port, System.Net.HttpListener listener, System.Boolean secure) [0x0009d] in <50d80b08c1a5449282b22aedf03ce925>:0
at System.Net.EndPointManager.AddPrefixInternal (System.String p, System.Net.HttpListener listener) [0x0005e] in <50d80b08c1a5449282b22aedf03ce925>:0
at System.Net.EndPointManager.AddListener (System.Net.HttpListener listener) [0x0009c] in <50d80b08c1a5449282b22aedf03ce925>:0
at System.Net.HttpListener.Start () [0x0000f] in <50d80b08c1a5449282b22aedf03ce925>:0
at Playground.Playground.StartHttpListener () [0x00016] in <d51cc6c047ee47c9a05c5e174876cbec>:0
at Playground.Playground.Main (System.String[] args) [0x00000] in <d51cc6c047ee47c9a05c5e174876cbec>:0
[ERROR] FATAL UNHANDLED EXCEPTION: System.Net.Sockets.SocketException (0x80004005): The requested address is not valid in this context
at System.Net.Sockets.Socket.Bind (System.Net.EndPoint localEP) [0x00043] in <50d80b08c1a5449282b22aedf03ce925>:0
at System.Net.EndPointListener..ctor (System.Net.HttpListener listener, System.Net.IPAddress addr, System.Int32 port, System.Boolean secure) [0x00047] in <50d80b08c1a5449282b22aedf03ce925>:0
at System.Net.EndPointManager.GetEPListener (System.String host, System.Int32 port, System.Net.HttpListener listener, System.Boolean secure) [0x0009d] in <50d80b08c1a5449282b22aedf03ce925>:0
at System.Net.EndPointManager.AddPrefixInternal (System.String p, System.Net.HttpListener listener) [0x0005e] in <50d80b08c1a5449282b22aedf03ce925>:0
at System.Net.EndPointManager.AddListener (System.Net.HttpListener listener) [0x0009c] in <50d80b08c1a5449282b22aedf03ce925>:0
at System.Net.HttpListener.Start () [0x0000f] in <50d80b08c1a5449282b22aedf03ce925>:0
at Playground.Playground.StartHttpListener () [0x00016] in <d51cc6c047ee47c9a05c5e174876cbec>:0
at Playground.Playground.Main (System.String[] args) [0x00000] in <d51cc6c047ee47c9a05c5e174876cbec>:0
PS:我明确想使用demindiro.com
, not *
.
PS2:我知道有很多关于这个特殊例外的主题,但似乎没有一个涉及HttpListener.Start()
抛出这个异常。
UPDATE我再次用谷歌搜索了我的问题,但这次我专门寻找TcpListener
我找到了这个答案:https://stackoverflow.com/a/17092670/7327379 https://stackoverflow.com/a/17092670/7327379
TcpListener 只能绑定到运行它的计算机的本地 IP 地址。所以你指定的IP不是本地机器的IP。您的公共 IP 与本地计算机的 IP 不同,尤其是当您使用某种 NAT 时。
如果我没记错的话,通常只使用 IPAddress.Any 作为您的 IP 来初始化侦听器。
因此,如果我明白这一点,这意味着要绑定到我的外部 IP,我必须以某种方式从这里开始
Server <-- local IP --> Modem <-- external IP --> The Internet
to this
Server <-- external IP --> The Internet
它是否正确?如果是,如何在没有调制解调器的情况下将服务器连接到互联网?或者我还应该做什么?