如何设置 TCP 套接字的本地端口?

How to set local port of a TCP socket?

为了在 C# 中设置 TCP 套接字,可以使用 System.Net.Sockets.Socket 如下(用于开始连接):

_socket = new Socket(AddressFamily.InterNetwork, 
                     SocketType.Stream, 
                     ProtocolType.Tcp);
IPEndPoint endpoint = new IPEndPoint(Ip, Port);
_socket.BeginConnect(endpoint, OnConnect, _socket);

这将创建一个套接字连接,endpoint 是远程端点,本地端点将自动创建(IP 地址将从...检索,端口似乎是随机选择的)。

为了修复本地端口,我尝试了以下方法(大致基于 this other post):

IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 
                                          cfg_DriverPort);
_socket.Bind(localEndPoint);

为什么是“127.0.0.1”?好吧,这就是众所周知的本地主机 IP 地址。

然而,这似乎不起作用:在 运行 之前的 BeginConnect() 之后:

_socket.BeginConnect(endpoint, OnConnect, _socket);

这是我在 window:

中输入 ? _socket.RemoteEndPoint 时得到的结果
'_socket.RemoteEndPoint' threw an exception of type 
'System.Net.Sockets.SocketException'
    Data: {System.Collections.ListDictionaryInternal}
    ErrorCode: 10057
    HResult: -2147467259
    HelpLink: null
    InnerException: null
    Message: "A request to send or receive data was disallowed because 
              the socket is not connected and 
              (when sending on a datagram socket using a sendto call) 
              no address was supplied"
    NativeErrorCode: 10057
    SocketErrorCode: NotConnected
    Source: "System"
    StackTrace: "   at System.Net.Sockets.Socket.get_RemoteEndPoint()"
    TargetSite: {System.Net.EndPoint get_RemoteEndPoint()}

那么,有人知道设置套接字本地端口的方法吗? (我认为“127.0.0.1”的把戏是个坏主意,但我不想 运行 遍历我所有的网络接口(我什至不知道该选择哪个)。

编辑
我尝试了 this answer, as proposed by Marc 的解决方案,但我失败了:

IPEndPoint endpoint = new IPEndPoint(Ip, Port);
IPAddress localipAddress = Dns.GetHostEntry(Dns.GetHostName()).AddressList[0];
var temp = Dns.GetHostEntry(Dns.GetHostName()).AddressList;
var temp2 = temp.First(add => add.AddressFamily != AddressFamily.InterNetworkV6);
IPEndPoint localEndPoint = new IPEndPoint(temp2, parent.cfg_DriverRemotePort);
_socket.Bind(localEndPoint);

我尝试过,使用localipAddresstemp2(我注意到localipAddress_socket.Connect()选择的不同,所以我想到了一种方法强制使用相同的 IPv4 地址(我不知道 IPv4/IPv6 是否与此有关,这只是强制使用地址的一种方式)。

老实说,我对这个请求的难度感到震惊:通常在远程 IP 地址和主机之间创建一个套接字,本地主机选择一个端口,然后在本地和远程端口之间建立连接,没问题。
现在我只要求使用我自己选择的端口,这似乎是一个负担。这是为什么?

Socket.Bind()IPAddress.Any 救援:

this other post中提到,可以使用Socket.Bind(),但是为了实现,必须填写IP地址,所以可以使用IPAddress.Any
起初,这等于 0.0.0.0,但是在执行 Socket.Bind() 时,这会被填充:

IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, cfg_DriverRemotePort);
_socket.Bind(localEndPoint);