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.
Related
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 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.
Kind hard to explain so here it is step by step:
Client sends data to Server via Udp. Client port X to server port 3000.
Server uses this communication to set up a UdpClient to listen for this specific client on port 3001 for client port X.
Client then sends data as needed on local port X to server port 3001.
Everyone is happy.
My question is: Can I assume that if the client is communicating to the server behind a NAT and it punches a udp port, that if it communicates to ANOTHER port on the same server that it will use the same port?
[Edit: formatting]
No you can not assume that. It may happen or it may not happen, it is up to the writers of the software of the NAT firewall the client is punching through.
A complex software may detect that you are talking to the same server but a different port and reuse the outbound port, but simpler software (the kind you would frequently see on home routers) may be "dumber" and just use a new randomized port per connection.
I am trying to make a winforms client/server chat application. I already have a client and a server, both are working fine, i can log in, send messages, etc .. The problem is that it only works if i connect to my local IP. When i try to run the program with my external IP, i get the following error:
"The requested address is not valid in its context".
In other words, i can run the server on my own computer, start up (for example) 3 clients and let them connect to the running server. This basically means that i'm talking to myself. What im trying to do is to run the chat server on my computer, and let other people run the client-program and connect to the server through the internet.
this is the part where i get an error when i enter my external IP:
public void StartListening()
{
// Get the IP of the first network device, however this can prove unreliable on certain configurations
IPAddress ipaLocal = ipAddress;
// Create the TCP listener object using the IP of the server and the specified port
tlsClient = new TcpListener(ipaLocal, 50702);
// Start the TCP listener and listen for connections
tlsClient.Start(); <--- THINGS GO SOUTH HERE
// The while loop will check for true in this before checking for connections
ServRunning = true;
// Start the new tread that hosts the listener
thrListener = new Thread(KeepListening);
thrListener.Start();
}
im not sure if what i'm trying to do is possible? i can't imagine it is, but i kinda dont know how to proceed with this. I'm new to network programming so any help will be appreciated.
kind regards,
Jane
Jane,
I think your issue is with your IP address setup. This is a network connection problem. You need external IP address so that outside clients can contact your PC. You need more advanced networking. The IP address provided from you ISP is used for domestic uses. You need specialized public IP address so that clients can find you outside of the firewall. This is networking/ISP/external IP issue.
Your server application needs to listen to incoming connections on a specified port, on a specified locally installed NIC. That is why TcpListener always needs to be created using a local IP address: because it only cares which NIC (if you have multiple installed) it should use.
The MSDN page for TcpListener also states it explicitly:
TcpListener Constructor (IPAddress, Int32) Initializes a new instance of the TcpListener class that listens for incoming connection attempts on the specified local IP address and port number.
External IP address is completely irrelevant to a TCP/IP server. You can have numerous routers and network devices along the way, which can then forward incoming connections to your machine.
Just do make sure that your firewall and router are configured properly to allow incoming connections on a specified port. To do that, start your TCP/IP server to open the port, and then use a service like CanYouSeeMe to see if server can be reached from outside.
Regarding your comment (this can prove unreliable on certain configurations), it's obviously "unreliable" when you think about it: a laptop can easily have an Ethernet network controller with a completely different IP address than a Wifi network adapter. Your server app should allow the user to select which IP address to use, instead of picking the first address it gets.
Ok so I've been trying to teach myself some socket programming. I wrote myself a little C# application with an async server and I understand most of it, except for the following:
So the server has a port it listens on for connections then when it receives a connection it creates a different socket to do the communication on. This it what I dont understand... How does the communication happen between the client and the server when in theory the client has no idea what port has been elected for this new connection?
Thanks for all your answers
Edit: As far as I understand the listening thread listens on the default port, but all messages are then handled on a different socket for each client?
Edit Again: Some how you guys are misunderstanding my question. I understand normal socket communication. My problem is with an async server where the listening socket is different from the connecting socket. Ie.
Server listens on default port
Client attrmpts to connect.
Server receiver request.
Server then creates a communication socket between client
and server and continues listening
on the default port.
My problem is at the last step. How does the client now know how to communicate on the new socket?
Here is some sample code
http://msdn.microsoft.com/en-us/library/5w7b7x5f.aspx
Although this question was posted over a year ago, I belive it is worth trying to clarify (or confuse?) it a bit more.
"How does the client now know how to communicate on the new socket?" - The client is not aware that a new socket was created. It simply keeps on sending data (packets) to the same port.
However, this gives rise to another question: How does the server know which data comes from which client? - Thanks to the TCP and IP protocols the server knows both the address of the client and the source port from which the packets were sent. With this information the server can receive packets from multiple clients and multiple (client) ports and route them to the correct socket. For this question, think of server sockets as filters: when packets are received from client X - port Y then route them to socket Z.
"...does it now know it needs to communicate on a different socket/port?" - This is a frequent source of confusion. When a new socket is created on the server to receive packets (after the connection has been established) it does not use a new port, it keeps on using the original port number. The entire socket creation process on the server side is transparent to the client. The client never knows (nor does it need to know) that a new socket was created to handle its packets.
Google TCP header for more information.
Hope this helps someone.
When the client connects to the server, it selects the port to connect to. The client also includes a port that it will receive responses on. This is typically a randomly selected port, but it's possible for the client to override that.
Think of it like a phone call. When you call someone, there is the phone number you call, and you also have a phone number. even though you both talk to each other, both phone numbers are in use.
That's not a perfect analogy, since phone numbers are more like IP addresses and trunk lines need not have an originating phone number in all cases, but the same concept applies.
Simply put, the TCP protocol requires an originating port and destination port as well as originating ip address and destination IP. When packets are sent in either direction, the apropriate IP/Port is used either way.
Actually the new connection use the same port. A server listen on a specific port for incoming connection, anytime it receives connection request from client, the server accept it and create a new thread to process the request. And then continue to listen on that port.
Definitions
Client: The socket at the remote machine that is connecting to the server
Server: The socket that is waiting for connections on the server
ServerClient: The socket which is communicating with the Client
Answer
I couldn't find any details about how the ServerClient port is transfered to the Client after the Server has accepted it. But it's most likely transfered in the handshake. Feel free to read RFC793 if you want to know more.
I wont go through the details, but you can read about passive connects to get more information about how listener sockets work at lower levels. But basically the purpose of listener sockets (Server) is only to accept sockets (ServerClient).
The port that the ServerClient uses is assigned by the socket implementation in the operating system and is nothing that you can control. All you need to know is that the each connected ServerClient will get it's own port and it's transfered to the Client during the (threeway) handskake (I think ;))