Search code examples
c#socketstcpportendpoint

How to set local port of a TCP socket?


In order to set up a TCP socket in C#, one can use System.Net.Sockets.Socket as follows (for beginning the connection):

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

This will create a socket connection with endpoint being the remote endpoint, the local endpoint will be created automatically (IP address will be retrieve from ..., the port seems chosen randomly).

In order to fix the localport, I've tried the following (loosely based on this other post):

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

Why "127.0.0.1"? Well, that's the wellknown localhost IP address.

However, this seems not to work: after having run the BeginConnect() from before:

_socket.BeginConnect(endpoint, OnConnect, _socket);

This is what I get when entering ? _socket.RemoteEndPoint in the immediate window:

'_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()}

So, does anybody know of a way to set the localport of a socket? (I believe the trick with "127.0.0.1" is a bad idea, but I prefer not running through all my networkinterfaces (I wouldn't even know which one to choose).

Edit
I've tried the solution from this answer, as proposed by Marc, but I failed:

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);

I tried, using localipAddress and temp2 (I had noticed that localipAddress was different than the one, chosen by _socket.Connect(), so I thought of a way to force that same IPv4 address (I don't know if IPv4/IPv6 has anything to do with this, it's just a way to force the address)).

Honestly I'm shocked by the difficulty of this request: normally a socket is created between a remote IP address and host, the localhost chooses a port and the connection is made between local and remote port, no problem.
Now I just ask to use a port which I choose myself, and this seems to be such a burden. Why is that?


Solution

  • Socket.Bind() and IPAddress.Any to the rescue:

    As mentioned in this other post, Socket.Bind() can be used, but in order to achieve that, the IP address must be filled in. therefore IPAddress.Any can be used.
    At first, this is equal to 0.0.0.0, but while performing Socket.Bind() this gets filled in:

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