I have been trying to setup a basic scenario where a TcpClient connects to a TcpListener on the same machine, but so far it only works for 127.0.0.1 and 192.168.X.Y. Here is my code:
var server = new TcpListener(IPAddress.Any, 51328);
server.Start();
var client = new TcpClient();
client.ConnectAsync(IPAddress.Parse("address from whatismyip"), 51328);
server.AcceptTcpClient(); // hangs indefinitely here
Console.ReadKey();
I got my external address from whatismyip but I'm not sure if I'm doing it correctly. Is something incorrect with my procedure?
I am assuming you are trying to connect over the internet? If you are connected via some Internet provider like COMCAST then you probably have a cable modem? To do this sort of thing you are going to need to setup PORT forwarding on a router.
The internet only see's your cable modem, all your requests to the internet go out as your cable modems IP, the router is able to "route" packets to and from your 192.168.x.x address on your behalf, so in order to have your 192.168 machine be able to listen and accept you must tell your router to forward any messages on port 51328 to your machine.
So your code would listen to port 51328 using the 192.168.x.xx address, then you setup the router. To test it you would connect using the public internet address that is assigned to your modem.
Related
I am trying to implement NAT hole punching for UDP datagrams for a simple Unity game. I have a public-available server (example.com) which is listening on both TCP and UDP on port 8995.
The idea for algorithm follows:
Client connects on TCP/8995 and specify the details of the game it want to host
Server reply with token
Client starts UDP socket via UdpClient class in C#
Client sends UDP datagram to server from this socket with the token. The server learns NAT Ip/Port of the client
When another client wants to connect, it asks server for the Ip/Port of the client it want to connect
The problem I have is step 4. I setup a client at my PC (192.168.1.1 port 9589) which is behind NAT and send my UDP packet to server. I received it via:
_listener = new UdpClient(_settings.EndPoint);
IPEndPoint source = new IPEndPoint(IPAddress.Any, 0);
var datagram = _listener.Receive(ref source);
_logger.LogDebug("Recevied UDP handshake from {EndPoint}", source);
The log I am getting here is Recevied UDP handshake from x.x.x.x:9589 where x.x.x.x is my correct public IP of the client.
Obviously the port I am getting in the log is not a temporary port on NAT, but a local port of the client behind NAT. So the Peer must have traversed the NAT to learn that (via UPnP maybe?). Is there any way to disable that behavior on server so I can learn the temporary port on NAT?
I am using Net Core 6 and Ubuntu server
Obviously the port I am getting in the log is not a temporary port on NAT, but a local port of the client behind NAT.
You get the port assigned by NAT, not the port used by the client on the LAN. These ports can be the same, because many NAT implementation try to do port preservation if possible.
I have a rather complex client server app that has three separate UDP connections.
One connection (port 50001) is for control of a device.
This connection listens for connections from a remote device and when a connection is made sends data and receives data. This works fine over a LAN as well as over the internet. Of course, port forwarding is enabled on the server network. This works fine using a mobile phone hot spot as well.
Another connection is for UDP sound being sent from the client to the server (port 50002). In this case, the client just sends UDP packets to the server using the routers internet IP Address which then by port forwarding goes to the server. This works fine over the LAN, and the Internet using a mobile phone hot spot.
Now there is a third connection (port 50003) where the issue comes in.This connection is the client receiving sound from the server. This works if I am on the lan and connect direct to the server or if I specify the Internet address of my router. But it does not work with a hot spot.
So the question is, is this an issue with the Mobile provider that is just not letting the UDP packets in over port 50003? Or, am I not connecting correctly to the hotspot?
So this is how the code works: When the connection is made from the client to the server for control of the device, I get the remote IPEndpoint address and save it. Next I just start sending the UPD packets from the server to the client using this address. Again this works over the LAN direct to the client, but it does not work if I use a hot spot.
Here is the code:
Note:address contains the address of the remote client from the first connection:
private void Connect(string address, int port) //at this point the control connection is running and the address comes from there
{
IPAddress destination = IPAddress.Parse(address)
socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
endPoint = new IPEndPoint(destination, port);
}
private void SendBytes(Byte[] bytes)
{
socket.SendTo(bytes, 0 , bytes.,Length, SocketFlags.None, endPoint)
}
So this exact same code works in the direction from client to server but in that case I am sending the UDP packets to the router internet address which has port forwarding enabled. However, it does not work in the direction from server to client. The question is why not?
Is it because a port forward is not available on the hot spot?
Why is one not needed for the control (Connection one??).
I should mention that the control connection is different than both of these: It is an async UDP server.
Thanks
Your assumption that the problem is on the missing port forwarding of the hot spot is correct.
Often the IP addresses provided by the hot spot are from a private range (e.g. 192.168.x.y) and are translated with NA(P)T to the public IP address of the hot spot.
When you send an UDP message from the client to the server, the router in the hot spot keeps the information of the source and targets IP addresses and ports. When an answer is received using the same IPs and ports, this message is forwarded to the client.
But when you use a different port number, the router doesn't know to who this message should be sent.
If possible, I would suggest that the third connection is also initiated by the client or that the data is sent over one of the other two existing connections.
my Sockets are correctly working in my local network, but when sending the program to a friend, he cant connect to me.
I host the server with this Code:
Socket listener = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
listener.Bind(new IPEndPoint(IPAddress.IPv6Any, 30000));
listener.Listen(500);
And he connects to this server using my external IP address (gotten from http://whatismyip.org/) and my specified port (30000) with this code:
Socket inOut = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
inOut.Connect(new IPEndPoint(IPAddress.Parse(textBox5.Text), 30000));
When using cmd netstat -a i cant find a listening entry with port 30000, so i guess that my server has the wrong settings or i need to specify something different, but i already opened the port in my router (30000).
As-is, the code you have shown should work, IF all of these conditions are met:
your ISP has assigned your Internet connection an IPv6 address. Ask your ISP. Many ISPs don't do this yet for home users. If your ISP has not, your client will have to use AddressFamily.InterNetwork (IPv4) instead. Depending on what kind of IP your client wants to connect to, it needs to create an appropriate Socket type. An IPv4 socket can't connect to an IPv6 IP address, and an IPv6 socket can't connect to an IPv4 address (unless it is configured to be a dual-stack socket).
your ISP is not blocking inbound TCP connections to your Internet IP. Many ISPs do, so they can charge customers extra for hosting their own servers. Most home Internet users don't need to run their own servers. Ask your ISP if this feature is enabled for your Internet account.
your router is configured to forward inbound packets received by the router's public IP address on port 30000 to your server's LAN IPv6 address on port 30000. If your router does not have a public IPv6 address (because the ISP hasn't assigned one), you will have to use AddressFamily.InterNetwork on the client side. Because a router is sitting between the client and server, they can use different IP versions to communicate with the router.
your server code is calling listener.Accept() or Listener. BeginAccept() after listener.Listen() exits without error. This is a given if your code already works on the local LAN, but I'm throwing it in anyway for good measure.
Try doing AddressFamily.InterNetwork instead of AddressFamily.InterNetworkV6
I'm building one client server application in c# where server is remote host. I've router and firewall in my network.
My client side code is
hostSocket = new TcpClient();
hostSocket.Connect(serverIp, serverPort);
And My server side code was
eqListner = new TcpListener(IPAddress.Parse(eqIp), eqPort);
in this scenario I'm able to connect client on same pc by giving ip 127.0.0.1 but cannot connect when I ran server on another pc in my network.
Then I've changed my server side code by following:
IPAddress ipAddress = Dns.GetHostEntry(Dns.GetHostName()).AddressList[0];
IPEndPoint ipLocalEndPoint = new IPEndPoint(ipAddress, eqPort);
TcpListener eqListner = new TcpListener(ipLocalEndPoint);
But still the result is same. Then I changed my server side code again by this:
eqListner = new TcpListener(IPAddress.Any, eqPort);
And this works perfectly fine. I've read msdn for IPAddress.Any and found that this property set server to listen for client activity on all network interfaces.
My question is why IPAddress.Any needs to connect to remote host? and other functions cannot connects?
Thanks in advance....
in this scenario I'm able to connect client on same pc by giving ip 127.0.0.1 but cannot connect when I ran server on another pc in my network
127.0.0.1 is the loopback address that is always the local host. When the service and the client are only on the same machine this can be convenient.
You are better off coding services to listen on all interfaces, this way should the server change address your application doesn't need to be updated or restarted.
The problem may be in the first line.
IPAddress ipAddress = Dns.GetHostEntry(Dns.GetHostName()).AddressList[0];
It will get the first ip of the host were it is running. That may be a IPv6 or localhost address.
If you want to listen in a specific address, it will be better to add it to project settings. It will be stored in app.config, and you can change it without recompile.
I've spent the last month writing a multiplayer game. I have only been testing it on one machine, using 127.0.01:9051 as the IPEndPoint.
I changed the IP address to my WAN IP, configured port forwarding on my router, configured my software firewall etc... But, it doesn't connect.
I have checked if the port is open using this site. Result: the port is really open.
Also, when I check the port from that website, my server receives packets just fine; however, when I connect from my own machine... it doesn't receive anything.
I've broken everything down to the basics to make sure it wasn't a problem with my code.
This basic code does not work:
IPEndPoint iep = new IPEndPoint(IPAddress.Parse("XXX.XXX.XXX.XXX"), 9051);
TcpClient client = new TcpClient();
client.Connect(iep);
Any ideas are much appreciated.
If you are attempting to connect to the IP that is Forwarded (outsideIP) to the same machine (insideIP), it won't work. There are very few enterprise firewalls and no consumer devices (I know of) that will route a packet from the inside out and translate it back in.
[Internet] -- outsideIP[Router/Firewall]insideIP1 -- insideIP2[Computer]
In this case, packets from insideIP(X) will not be able to connect to outsideIP.
Try to see if you can telnet to your wan IP on port 9051. Routers don't really like it when you connect to their wan IP from within the network itself.
You could use Dyndns or some other service for the outside world to connect to your server and put the same name into your host file that resolves to 127.0.0.1 so that you can connect internally.
Is your client and your server (both the same machine in your failing test) using the same endpoint ip/port? You can only bind a port once at a time. Try using two ports one for server in one for server out (clinet in). That way they will not clash. Use Telnet to check you can connect to the IP/Ports you are using and Netstat to check they are not in use already.