Bind new port Http Client (ipv4)

Marcos Santos

Member
Joined
Nov 11, 2021
Messages
11
Programming Experience
1-3
I have a vps with multiples IP and every request I send to my API I use a different IP (I specify on the request, see the method).

The problem is, if I bind on port 0 only, port gets so slow due, but If I use a different port I get the error:

Error
C#:
Unknown Error => System.Net.Http.HttpRequestException: Only one usage of each socket address (protocol/network address/port) is normally permitted. (myapi:443)
 ---> System.Net.Sockets.SocketException (10048): Only one usage of each socket address (protocol/network address/port) is normally permitted.
   at System.Net.Sockets.Socket.UpdateStatusAfterSocketErrorAndThrowException(SocketError error, String callerName)
   at System.Net.Sockets.Socket.DoBind(EndPoint endPointSnapshot, SocketAddress socketAddress)
   at System.Net.Sockets.Socket.Bind(EndPoint localEP)

http client:
        public static HttpClient GetHttpClient(string ip, int i)
        {

            Random rnd = new Random();

            IPAddress ipAddress = IPAddress.Parse(ip);

            if (IPAddress.Any.Equals(ipAddress))
                return new HttpClient();

            SocketsHttpHandler handler = new SocketsHttpHandler();

            handler.ConnectCallback = async (context, cancellationToken) =>
            {
                Socket socket = new Socket(SocketType.Stream, ProtocolType.Tcp);

                socket.Bind(new IPEndPoint(ipAddress, 3));

                socket.NoDelay = true;

                try
                {
                    await socket.ConnectAsync(context.DnsEndPoint, cancellationToken).ConfigureAwait(false);

                    return new NetworkStream(socket, true);
                }
                catch
                {
                    socket.Dispose();

                    throw;
                }
            };

            return new HttpClient(handler);
        }

HttpClient client = HttpController.GetHttpClient(ip, port);
 

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
4,029
Location
Chesapeake, VA
Programming Experience
10+
When you used to pass in 0, it let the system pick any available port:
port Int32
The port number associated with the address, or 0 to specify any available port. port is in host order.

 

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
4,029
Location
Chesapeake, VA
Programming Experience
10+
Perhaps I'm missing something, but usually one only uses Bind() when they are about to Listen(), not when you are trying to Connect(). Why are you trying to bind to port 3 on the local machine?

What does running netstat -aon say about which ports and addresses are already in use?
 

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
4,029
Location
Chesapeake, VA
Programming Experience
10+
I think you are specifying a port that is already in use. As I said, check what netstat -aon returns.
 

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
4,029
Location
Chesapeake, VA
Programming Experience
10+
What ports does netstat -aon show as being in use. Pick other port numbers which are in use.

Also, I'll repeat my questions from your other thread where you used:
C#:
if (IPAddress.Any.Equals(ipAddress))
                return new HttpClient();
How does your IPAddress collection get populated? Is it after after a successful connection is made, or after a HttpClient is created (but may not be necessarily successful)? How does it get depopulated as connections are closed?

Why do you return a generic HttpClient() without a custom sockets handler if you have IP address in your collection? Shouldn't you return that HttpClient() you had previously made for that IP address? Perhaps your IPAddress collection should actually be a dictionary so you can find those previous instances.

And now some new comments about the code above:

Only create one instance of a random number generator and use it throughout the lifetime of the application. If you create two random number generators with the same application timer tick, both generators will return the same sequence of random numbers because the default constructor for Random uses the current machine time, and the machine time resolution is lower than the speed of modern processors.

Next, you should not be creating HttpClient objects willy-nilly. Ideally you should only have one for the the entire lifetime of your app.


and

 

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
4,029
Location
Chesapeake, VA
Programming Experience
10+

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
4,029
Location
Chesapeake, VA
Programming Experience
10+
What's confusing is that you say your objective is for your client to connect to a server that has multiple IP addresses and ensure that it tries to use all the addresses. But the code you are presenting shows that you are using Bind() before connecting. That bind-before-connect sets the source IP and port, not the destination IP and port. Your stated goal was that you wanted to be able to set the destination IP address so that you could use all the server IP addresses.
 

Marcos Santos

Member
Joined
Nov 11, 2021
Messages
11
Programming Experience
1-3
What's confusing is that you say your objective is for your client to connect to a server that has multiple IP addresses and ensure that it tries to use all the addresses. But the code you are presenting shows that you are using Bind() before connecting. That bind-before-connect sets the source IP and port, not the destination IP and port. Your stated goal was that you wanted to be able to set the destination IP address so that you could use all the server IP addresses.

That's not the problem.

Every request has a different IPV4, I am passing which IP I want.

This specific api I can't bind another port, but any other api I can.
 

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
4,029
Location
Chesapeake, VA
Programming Experience
10+
Yes, you are passing in an IP address, lines 1 and 6, but you are setting that as the source address by binding on line 17.

Yes, you are succeeding with letting the OS select the source port and failing when you are forcing the port number, but that's not the issue I'm talking about. I'm talking about the conflict in your stated goal of hitting multiple destination IP addresses, but your code is setting multiple source addresses. It's like saying that you want to visit several other countries starting from your home country, but you are buying airline tickets where the flight starts in those countries. Shouldn't you be buying tickets for flights that start in your country, but end up in those other countries?
 
Last edited:
Top Bottom