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
Related
Is it possible to fetch the IP addresses of connected clients to a server from the client side? I know it's possible server sided, but is it client sided?
Note: I'm talking about server-client connection using a basic Socket.
Only if the server purposely provides that list.
Otherwise, it is not possible to get any information of other clients connected to a server you are connected to (this, of course, applies to Java, but can also be understood as a general concept of networking -- in the context of peer to peer, client/server, sockets).
Not without a script or program on the client end of the socket having code to retrieve it (e.g. Javascript on a web page). You cannot tell this strictly from the server side.
You are talking with your server, and only server talks with other clients directly. So only server can send you clients ip addresses.
So, this is possible, but must be implemented on server.
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'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.
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 have something like a proxy server (written in java) running between my clients and the actual video server (made in c++). Everything the clients send goes through this proxy and is then redirected to the server.
It is working fine, but I have some issues and think it would be better if I could make this proxy server only to listen to the clients requests and then somehow tell the server that a request has been made from the client side, and that it is supposed to create a connection with the client directly.
Basically in the TCP level what I want to happen is something like this:
1- whenever a client sends a SYN to my proxy, the proxy just sends a message to the real server telling the ip and port of the client.
2- The server would then send the corresponding SYN-ACK to the specified client creating a direct connection between client and server.
The proxy would then be just relaying the initial requests (but not the later data transfer) to the actual server. I just don't know if that is possible.
Thank you very much
Nelson R. Perez
That's very much the way some games (and Fog Creek CoPilot) do it, but it requires support on both the server and the client. Basically the proxy has to say to the client and server "try communicating with the directly on this ip and this port" and if they can't get through (because one or both is behind a NAT or firewall), they fall back to going through the proxy.
I found this good description of "peer to peer tcp hole punching" at http://www.brynosaurus.com/pub/net/p2pnat/
Does the proxy and server lives on the same machine? If so, you can pass the connection to the server using Socket Transfer or File Descriptor Passing. You can find examples in C here,
http://www.wsinnovations.com/softeng/articles/uds.html
If they are on the different machines, there is no way to pass connection to the server. However, it's possible to proxy the IP packets to server using VIP (Virtual IP). This is below socket so you have to use Link layer interface, like DLPI.
You don't have control of TCP handshake in userland like that. This is what firewalls/routers do but it all happens in the kernel. Take a look at the firewalling software for your platform - you might not even have to code anything.