I have an IoT device (most likely across NAT), which should communicate with server (on internet), and the server should be able to send commands to the device. Here's the high level communication details:
IoT device will send KeepAlive packet from port 9000 (say) to the server on a port 8000 (say). The server now has the port and IP (say Cp and Cip) which it could use to start a connection back with IoT device if needed.
Server is obviously listening for connections on port 8000. So Server has a server-socket to listen to IoT device's keepalives
The KeepAlive packets are sent periodically, and the connection are closed once the server returns OK. This is to ensure a socket is not kept open, saving resources on both server and IoT device.
Now, say I want to send some command to the IoT device, in that case, I want to open a socket connection from the Server on port 8000, and send packet to Cip, Cp.
The IoT device should receive this packet on its port 9000. For that to happen, the IoT device should open a server socket to accept these connections.
As we can see, both client and server have to open the server socket on a particular port, and occasionally there's a requirement to create a client socket on that port to send some data.
Would TCP work with above scenario? I'm just confused if Client socket and Server Socket could be bound to the same port?
Please suggest
EDIT 1:
I deliberately have chosen above design since keeping IoT device to server connection open all time does not scale. Say I have millions of IoT devices on the field, I'll need to load balance the connections now.
The server to IoT device (backward) connection is only to ensure the commands are immediately send. The forward connection (IoT device to server) is only created to send the keepalives. It would be done periodically (may be 5-10 mins apart)
EDIT 2:
The reason for a fixed port (8000) is this: The NAT opens up hole for reverse communication only from the destination port where the keepalive packet was received. So the reverse packet can be sent from a port X on server to IoT device only if a packet had been received from IoT device on that port.
Related
Golang application with a client and server.
Server uses net.ListenUDP -- client also uses net.ListenUDP, connects to server and sends a packet with conn.WriteToUDP with the server address.
Server receives the packet with ReadFromUDP and grabs the return address. Using this return address, it then sends a large number of packets back to the client.
When running both client and server on local machine, this works perfectly. Using Wireshark I can inspect the UDP packets and see that they contain the source and destination ports - and in the application I can see that they arrive and my various checksum tests show the data is accurate.
I then moved the server off site to a remote machine. The application stops working. I can successfully send the first message from the client to server - this is received just fine. The server sends the response back 'toward' the client - but the client never receives them.
Using Wireshark, I can see that the packets do arrive back on the local machine with the correct IP address. It appears that my network router has performed NAT on the outgoing packets - and has correctly re-addressed response packets to the internal IP.. BUT there is no port.
So I have UDP packets arriving on the correct machine, but no port - so the client application does not receive them. Application times out on ReadFromUDP.
I don't know if it is relevant, but on local machine, Wireshark labels the packets as BT-uTP Utorrent packets. When they come in from remote server, this is what I see in Wireshark - note the lack of Port.
Any thoughts how I can solve this. I didn't think this was a UDP hole punching problem because although I am establishing a connection across a NAT it is with a server not a peer.
This packet is fragmented, You can see this under Internet Protocol Version 4 > Flags.
If you look at the frame as shown on the bottom of the picture you provided you should see the ports.
net.ListenUDP doesn't appear to support fragmentation at the socket level.
Do you have a PPPoe connection? You may need to reduce your packet size being sent by 8 bytes or change the MTU on the routers external interface of the remote side. You may also need to change the local routers MTU if it's on a PPPoe interface.
I have to implement a server-client program using UDP connection setup.
In which Server UDP writes data packets to port XXXX continuously, and client at any moment just read data.
note : there should be no handshaking i.e server will not be knowing the client address at any point in time.
I have implemented UDP server-client program.
server uses client address and broadcast the packets.i.e there is handshake well before broadcasting data to client. (but this was rejected, has server knew client address and handshaking was involved)
I am expecting how to make UDP server independent of the client address, just write data to port, then after some time client connect to port and read the data. there is no server intervention in reading the data
If a client listens on a socket, at http://socketplaceonnet.com for example, how does it know that there is new content? I assume the server cannot send data directly to the client, as the client could be behind a router, with no port forwarding so a direct connection is not possible. The client could be a mobile phone which changes it's IP address. I understand that for the client to be a listener, the server doesn't need to know the client's IP.
Thank you
A client socket does not listen for incoming connections, it initiates an outgoing connection to the server. The server socket listens for incoming connections.
A server creates a socket, binds the socket to an IP address and port number (for TCP and UDP), and then listens for incoming connections. When a client connects to the server, a new socket is created for communication with the client (TCP only). A polling mechanism is used to determine if any activity has occurred on any of the open sockets.
A client creates a socket and connects to a remote IP address and port number (for TCP and UDP). A polling mechanism can be used (select(), poll(), epoll(), etc) to monitor the socket for information from the server without blocking the thread.
In the case that the client is behind a router which provides NAT (network address translation), the router re-writes the address of the client to match the router's public IP address. When the server responds, the router changes its public IP address back into the client's IP address. The router keeps a table of the active connections that it is translating so that it can map the server's responses to the correct client.
The TCP Iterative server accepts a client's connection, then processes it, completes all requests from the client,
and disconnects. The TCP iteration server can only process one client's request at a time. Only when all the
requests of the client are satisfied, the server can continue the subsequent requests. If one client occupies the
server, other clients can't work, so TCP servers seldom use the iterated server model.
I have a simple TCP socket client and server application. They are communicating using IP = localhost and port = 33367.
I'm using SocketSniff to examine my packets going through localhost. While sniffing the client app, I noticed that every time I'm sending a packet to the server in the same process, the "local port" is changing, while remote port is always 33367.
So, is it possible for the client apps to send their data through a fixed port (if so, how in C#?) or do they have to get assigned a different port each time?
You can bind the socket before calling connect.
After many hours, I have discovered that the given udp server needs the following steps for a successful communication:
1- Send "Start Message" on a given port
2- Wait to receive from server on any port
3- Then the port dedicated to you to send further data to the server equals the port you have received on it + 1
So I am asking if this kind is a known protocol/handshaking, or it is only special to this server??
PS: All above communication were in udp sockets in C#
PS: Related to a previous question: About C# UDP Sockets
Thanks
There's no special "handshake" for UDP -- each UDP service, if it needs one, specifies its own. Usually, though, a server doesn't expect the client to be able to listen on all of its ports simultaneously. If you mean that the client expects a message from any port on the server, to the port the client sent the start message from, then that makes a lot more sense -- and is very close to how TFTP works. (The only difference i'm seeing so far, is that TFTP doesn't do the "+ 1".)
The server is, effectively, listening on a 'well known port' and then switching subsequent communications to a dedicated port per client. Requiring the client to send to the port + 1 is a little strange
Client 192.168.0.1 - port 12121 ------------------------> Server 192.168.0.2 - port 5050
Client 192.168.0.1 - port 12121 <------------------------ Server 192.168.0.2 - port 23232
Client 192.168.0.1 - port 12121 ------------------------> Server 192.168.0.2 - port 23232 + 1
<------------------------ Server 192.168.0.2 - port 23232
------------------------> Server 192.168.0.2 - port 23232 + 1
The server probably does this so that it doesn't have to demultiplex the inbound client data based on the client's address/port. Doing it this way is a little more efficient (generally) and also has some advantages, depending on the design of the server, as on the server there's a 'dedicated' socket for you which means that if they're doing overlapped I/O then the socket stays the same for the whole period of communications with you which can make it easier and more efficient to associate data with the socket (this way they can probably avoid any lookups or locking to process each datagram). Anyway, enough of that (see here, if you want to know why I do it that way).
From your point of view as a client (and I'm assuming async sockets here) you need to first Bind() your local socket (just use INADDR_ANY and 0 to allow the OS to pick the port for you) then issue a RecvFrom() on the socket (so there's no race between you sending data to the server on this socket and it sending you data back before you issue a recv). Then issue a SendTo() to the 'well known port' of the server. The server will then send you back some data and your RecvFrom() will return you the data and the address that the server sent to you from. You can then take that address, add one to the port, store that address and from then on issue SendTo()s to that new sending address whilst continuing to issue RecvFrom()s for reading the server's data; or you could do something clever with Connect() to bind the remote end of the socket to the server's 'send to address' and simply use Write() and RecvFrom() from then on.