I've got UDPserver which recieves messages from clients and sends response to them. But I need to check if UDPclients is online or not.
With isReachable I can test whether pc online or not. But when differents clients use same pc but with differents ports how to check whether port is open or not(Client1 with port 5678 is online but client2 6777 is off.IP 192.168.1.7 IP isReachable in this case but client2 is not)?
UDP is a connectionless, unreliable packet-oriented protocol. If there is no socket bound to a particular port on the remote machine then the packet will simply be dropped.
You would have to implement some sort of protocol which supported detection of whether a client is online or not. Perhaps sending a keep-alive type message periodically.
You're conflating two different concepts here. The 'isReachable' function is an IP-layer property which is simply checking to see if the IP address in question is responding to IP-protocol packets (which it is).
UDP is a broadcast datagram protocol designed for unacknowledged data broadcasts over IP, so it has no inbuilt concept of 'reachability'. Your UDP client must somehow watch for incoming detection messages, and respond to them accordingly.
IsReachable will only do a ICMP echo request (ping) on the given host so event if your client is not running but as long as your host responds to ICM requests it will show as reachable.
If you which to check if your remote client is running, you will need to implements a simple "ping" protocol : ie: your server will send a special message to the client and the client has to respond to it.
If the only issue is to know if a client is alive, then keep-alive message from the client is easiest. You can identify the client for example from the content of the package (or the sender port).
If you wish to send messages to the clients, I think you'll have to have a UDP server on both ends, and then exchange the ports the 'client-servers' are listening on and use that for communications.
Of course, the latter will cause issues with firewalls as most will block all incoming traffic.
Related
I've seen many answers similar to this one in regards to serversockets in java: "Let's say you have a server with a serversocket on port 5000. Client A and Client B will be connecting to our server.
Client A sends out a request to the Server on port 5000. The port on Client A's side is chosen by the Operating System. Usually, the OS picks the next port that is available. The starting point for this search is the previously-used port number + 1 (so for instance if the OS happened to us port 45546 recently, the OS would then try 45547).
Assuming there are no connection problems, the Server receives Client A's request to connect on port 5000. The Server then opens up its own next available port, and sends that to the client. Here, Client A connects to the new port, and the server now has port 5000 available again."
I've seen answers like this in multiple questions on stackoverflow about how a different port is used in the returned socket of the accept() than the port that the ServerSocket is listening on. I was always under the impression that TCP is identified by the quartet of information:
Client IP : Client Port and Server IP : Server Port ->protocol too (to distinguish TCP from UDP)
So why would the accept() need to return a socket bound to a different port? Doesn't the quartet of information sent in every header distinguish multiple connections to the same server port from different machines enough where it would not need to use different ports on the server machine for communication?
The Server then opens up its own next available port, and sends that to the client.
No. It creates a new socket with the same local port number. No second port number is allocated or sent to the client. The SYN/ACK segment which is the server's response to the connect request does not contain a second port number.
Here, Client A connects to the new port,
No. The client acknowledges the SYN/ACK packet and the client is connected to the original port from then on, after acknowledging the SYN/ACK. There is no second connect.
and the server now has port 5000 available again."
It always did.
I've seen answers like this in multiple questions on stackoverflow about how a different port is used in the returned socket of the accept() than the port that the ServerSocket is listening on.
Any such answer is incorrect and should be downvoted 'with extreme prejudice' and commented on adversely. The TCP handshake is defined in RFC 793 and does not specify allocation and exchange of a second port and a second connect message. There are only three messages, which isn't even enough for that to occur.
So why would the accept() need to return a socket bound to a different port?
It doesn't.
Doesn't the quartet of information sent in every header distinguish multiple connections to the same server port from different machines enough where it would not need to use different ports on the server machine for communication?
Yes.
You are correct in the TCP packet header's information. It contains:
Client IP | Client Port | Server IP | Server Port | Protocol
Or, more appropriately (since client/server become confusing when you think about bi-directional transfer):
Source IP | Source Port | Destination IP | Destination Port | Protocol
Multiple connections to the same server port will come from different ports on the client. An example may be:
0.0.0.0:45000 -> 1.1.1.1:80
0.0.0.0:45001 -> 1.1.1.1:80
The difference in client ports is enough to disambiguate the two sockets, and thus have two separate connections. There is no need for the server to open another socket on another port. It does receive a socket from the accept method, but it's assigned to the same port and is now a route back to the newly accepted client.
FTP, on the other hand, does have a model where the server will open a new unprivileged port (> 1023) and send that back to the client for the client to connect to (this is referred to as "Passive FTP"). This is to resolve issues where the client is behind a firewall and can't accept incoming data connections from the server. However, this is not the case in a typical HTTP server (or any other standard socket implementation). It's functionality that is layered on top of FTP.
I am new to socket programming and I need to clarify some things.
Do you need a server between two client communication? Let me explain what I mean:
Example 1:
Client1: Server, I want to talk with a client2
Server: No problem. Let's just wait until he sends the request to connect
Client2: I'm here. I want to talk with client1.
Server: Okay Client1 here is Client2 IP address. And for you Client2, here is
Client1 IP Address. You can now talk to each other without me.
Example 2:
Client1: Server, please send client2 a message: "Hey client2. How are you?"
Server: Okay no problem. Sending message to client2
Client2: Server thanks for sending client1's message. Send him a reply: "Hey, I'm fine."
Server: Sending message to client1..
So my question is: Do you need a server after you met two clients together to communicate between them? Or I'm on completely wrong track?
EDIT:
The purpose behind this is that I want to expand my very simple mobile game to become a multiplayer. Just for example, I want to show PACMAN2 on PACMAN1 mobile phone and vice versa.
If you are using a TCP socket programming, you need central server to facilitate communication between clients.
Reason - You cannot connect to a port on one client from every other client. All clients can connect to one server on a particular port and server can facilitate the communication among clients.
If you move away from socket programming and use advanced features like Messaging; peer to peer communication and broadcasting of messages to multiple clients can be achieved.
EDIT:
Still I prefer TCP over UDP for these reasons especially Reliability
In your case of multi player games, still your clients need to be connected to server on dedicated socket. Since you have to use TCP anyway, server can take care of sending messages between clients with client id.
yes, you can do with peer to peer communication does not need any central server or you can also use sockect or you can communicate with user ip address.
Ref
peer to peer
Having the two client applications could theoretically communicate directly and this could work in a LAN but in practice it is unlikely. The main reason this won't work is that in many cases the IP address of client 1/client 2 that the server "sees" is actually the IP address of the network gateway for client 1/client 2 which means that client 1 cannot initiate a connection to client 2. Also you can have the firewall on client 2 machine (or its network) blocking the connection initiated from client 1.
You might find useful information if you read more on XMPP.
To put what Kevin Kal said into a answer:
no you do not necessarily need a server for Client1 and Client2 to talk to each other. If you use the server in your example to send the necessary data (IP and port) to Client1, Client1 can connect to Client2 via a socket Client2 listens to (and as Kevin said, this makes Client2 into a server, strictly speaking.)
If you want to know more about Client to Client connections in java here's a really good answer to a similar question:
Connect two client sockets
I am working with a Java desktop server and multiple Android clients connected to it. on the server side I need to identify which client has sent me a message by sockets TCP/IP and send a response only to that one client and not the others.
I will store all the sockets of clients in an ArrayList.
first here are two ways that I tried that don't work;
-- the IP address of the client, get this by calling socket.getLocalSocketAddress() in the client and socket.getRemoteSocketAddress() in the server, but they never match. for example i got in the client XXX.XXX.11.17 and in the server XXX.XXX.0.13, they are supposed to be the same for the same connection.
-- the port number, get this by calling getLocalPort() in the client and getPort() in the server, yes this works perfectly and the numbers match so I can use this, HOWEVER there is a possibility that the randomly selected port numbers on two different clients could be the same. not likely but possible. so that means there is no guarentee that they are unique.
what is the alternative that I can use that will work?
I need to identify which client has sent me a message by sockets TCP/IP and send a response only to that one client and not the others.
Send it back down the same socket you received the request from.
If you need a permanent identified for the client, you can use the result of Socket.getRemoteAddress().
getLocalSocketAddress() in the client and getRemoteSocketAddress() in the server [...] are supposed to be the same for the same connection.
No, because you don't know what's in between. Most mobile providers use proxies, NAT and so on. The mobile device thinks it's on a LAN (10.0.0.x or 192.168.x.x addresses) which the provider provides. It's even possible for multiple clients to have the same remote address (as seen from your server).
That being said, you can uniquely identify a client in your server application by the remote IP address and port combined together, given the server listens on one IP, port and protocol. This information is available from socket.getRemoteSocketAddress(), where the returned InetSocketAddress (in case of an internet socket) contains both the remote IP and port (getAddress() and getPort() respectively).
But as indicated by the other answer, you don't really need a way to identify a client. A network client is identified by the socket you receive data on (a socket is an exclusive connection between two nodes), so just send the data back to the socket that you received the request on.
If you do need more bookkeeping data about the connected client, wrap the client socket in a wrapper class that contains additional information.
I am writing this game in Java and have problems with networking architecture.
I decided I will UDP packets. I am just at the beginning, but the problem I am facing is that it seems to be that server have to respond from exactly same IP/Port to client (which is behind router which uses NAT) as client connected that server.
For example I have client A behind router. Client A has IP (local) 192.168.8.100 and it connects server B from port 1234. Server is on 11.11.11.11:2345.
When client A connects to server B it uses 192.168.8.100:1234 but router converts that to (for example) 22.22.22.22:6789.
Now, when server wants to send packets to that client it has to be from 11.11.11.11:2345.
I would like to send data from another port like 11.11.11.11:2222, but this does not seem to work, at least not with my router.
I want to use different port because I want to have two threads one for listening and one for sending data, and each thread would have it's own DatagramSocket. But, as i said once client A connects to server on port 2345, I can not send data from port 2222.
Does anyone know how is this handled? I am doing it in Java, but it's not really a language specific problem.
UPDATE
After #Perception commented I have some more questions regarding his comments:
OK, so if I understand this correctly, if I have server which is hosting 1000 games, each with 2 players, all sending/receiving will have to be done through the same DatagramSocket.
As I understand DatagramSocket is thread safe so I guess I can have one thread doing:
datagramSocket.receive();
while at the same time second thread is doing
datagramSocket.send(.....);
Correct?
Also, two threads can send data at the same time through the same DatagramSocket? Is sending in any way serialized, meaning that second send() starts only after previous send() is finished or is data being sent at the same time?
gorann, I'm not sure if I'm understanding you correctly, but it sounds like you're trying to control the port on which the server communicates with the client. There's no way to control this, and for good reasons.
This is one of the trickier differences between TCP and UDP.
When a new TCP session is initiated, the server side call to accept() gives you a new socket and the OS handles multiplexing the various sessions for you. With UDP, you need to handle the multiplexing yourself. But you need to do so in a way that works with NATs and other firewalls.
The way NAT works is that when it sees an outgoing packet, it creates a temporary rule allow packets to return along the same port pair. Data returning from a port that the client has not yet sent to will likely be blocked.
This gives you two choices:
You could do all of your communication through a single port. This is not a bad option, it just means that you need a way to identify client sessions and route them to the appropriate thread.
You could create a separate port and instruct the client to send to that one instead. Have the server listen on a fixed port. The client sends a message to there, the server then sets up a new session port and sends that number back to the client using the server's listen port. The client then sends a message to the session port, which causes the NAT to open up that port and allow return traffic. Now the client and server thread have their own private port pair.
Option 1 is a bit more work because it requires data to be exchanged between threads, but it scales up better. Option 1 is easier and more CPU efficient because each session thread can be independent, but there are a finite number of ports available.
Either way, I recommend that you have the client include a semi-unique session id in each packet so that the server has more than just the client address and port number to verify who belongs to each session.
I am writing a distributed Java app, but the networking side of things is stumping me. For some reason it's not working correctly. I think it's because the IP address I get through ipconfig /all is not accessible from outside the LAN. I appreciate any tips or advice.
Overview
You need what is commonly-known as "NAT Traversal", or ICE. There are two primary protocols used on the internet today TCP and UDP. TCP sockets carry a significant amount of session state information in them; consequently it is a significantly more difficult protocol to use for P2P than UDP.
UDP Tunneling
The following list is a simplified outline of the more general STUN Protocol (RFC 5389) that you could use to implement a P2P service based on UDP NAT Traversal...
Deploy a UDP server with a public address and start listening for UDP packets from your clients. Clients will embed their private IP address inside the UDP packets sent to your server; it would be a good idea to implement some form of authentication to ensure you are getting connections from a valid client (instead of some random packet scanner).
The server reads how their private IP address has been translated into a public IP address from the UDP Datagrams.
If you want to make connections between specific users, also embed this information inside packets sent from the clients to your server; your server will implement a username directory to associate client UDP socket information with usernames (that peers will try to connect to).
Your UDP server should send the corresponding information back to the other relevant peer(s).
Now, peers can communicate directly by sending UDP datagrams to these translated addresses; these packets will go through client NAT devices in the path as long as the UDP ports in question are allowed and the delay introduced by this protocol does not trigger state timeouts in the NAT devices.
After you have established UDP connectivity, you could form an UDP SSL VPN between the two clients using something like OpenVPN; this would give you a trivial channel to initiate a TCP connection between the clients. However, there are non-trivial security and trust issues to consider in this connectivity model; it is unlikely to be useful between random users on the internet.
TCP
If TCP connectivity is required, I suggest looking at this internet draft, MMUSIC-ICE-TCP: TCP Candidates with Interactive Connectivity Establishment (ICE)
some ip address are not routable: http://en.wikipedia.org/wiki/IP_address - if you have one of those, you wont be able to access it from outside the lan directly. you can access the other addresses on your lan from one that is on that lan.
if you are outside the lan, you can not start a tcp connection to a specific machine on the lan, but that machine can start one with you: http://en.wikipedia.org/wiki/Network_address_translator