I am very new to network programming, so this might be a no brainer. What I was wondering is, I know TCP requires the client to know the IP of the server. But since UDP is connectionless server, is it still required? I mean can I make my server broadcast it's IP address on a specific port ( not necessary in the same LAN , also over internet) and make the clients listen to that port for any incoming requests and find get the IP of the server once a request is received ?
You can try to send packages on specific port over the LAN. But for the Internet no.
Look into using ARP/RARP if that gives you what you need. Coming to your question
Mind you both TCP and UDP require IP addresses binding the ip address to a port is called a socket and there can be TCP and UDP with the same port no.
You can do this according to what you said but then the server needs to know the client addresses
Create a connection from server to client
Send IP address of server to client
Client send data using just received Server IP
to work around this you can use the broadcast address of the network and have the clients listen to it, just check what your broadcast address is.
What you are trying to do is similar to a DHCP server.
Related
I am trying to build an android application that connects two or more devices as a client/server(using socket).
But problem is in client device user need to manually put IP address of Server device to connect with server. But from the client i don't know the server IP Address. and i don't want to enter it manually.
is there any way to get IP address(programmatically) of server device that using same application and on the same network ?
Any help would be greatly appreciated.
Thank in advanced.
After trying many ways finally, I have got a solution which is
Network discovery using UDP broadcast (credit goes to this documentation)
(Thanks #Fildor for your suggestion to implement this service).
Solution
Using UDP packets and broadcasting them! This technique however is not optimal, but as long as we stay in one network this shouldn’t be a problem.
UDP packets however are fairly easy to work with.
Server implementation
Open a socket on the server that listens to the UDP requests.
Make a loop that handles the UDP requests and responses
Inside the loop, check the received UPD packet to see if it’s valid
Still inside the loop, send a response to the IP and Port of the
received packet
Client implementation
Open a socket on a random port.
Try to broadcast to the default broadcast address (255.255.255.255)
Loop over all the computer’s network interfaces and get their
broadcast addresses
Send the UDP packet inside the loop to the interface’s broadcast
address
Wait for a reply
When we have a reply, check to see if the package is valid
When it’s valid, get the package’s sender IP address; this is the
server’s IP address
CLOSE the socket! We don’t want to leave open random ports on someone
else’s computer
I want to know if there is a way to broadcast data through udp sockets for clients behind a NAT. I found many examples where the server is sending data to a multicast address and clients listen on a fixed port. But if there is a NAT between them, the packages need to be sent to different ports, depending on how the NAT has created the port translations right ? So what is the solution here ?
I am trying to create a java chat application for my networking class. As of right now I am stuck trying to connect to someone behind a different router. The way I have my project right now is I have a client program and a server program. The client programs first logs into the server program which logs their IP and port in a database and then the server gives them back the list of their friends with their IPs and ports. Then the client closes down the connection to the server and tries to connect to another client using the information the server sent back. So far my program only works connecting to the server and getting the friends IP and port but when I use those values to connect to the other client I cant connect.
socket = new Socket();
socket.setReuseAddress(true);
socket.setKeepAlive(true);
socket.setSoLinger(true, 10);
socket.bind(new InetSocketAddress(Port));
socket.connect(new InetSocketAddress(host, SERVER_PORT));
reusePort = socket.getLocalPort();
Above is a snippet of java code used to connect to the server then below is what i do on the client side.
ss = new ServerSocket(reusePort);
So now technically I am listening on the same port I used to connect to the server with which is logged in and is retrievable to another client and is in the NAT table with my ip and port. I am not sure what I am missing or if there is some protocol or something that I have to do. I have looked at TCP and UDP hole punching but I am not sure how that is actually accomplished or how to implement it.
Any suggestions would be appreciated.
If you want to send a message you'll need to set up port forwarding on any device that acts as a server (any device which creates a socket server). Port forwarding is done on the Router. The reason you cannot connect to the other client is because they are hidden behind their routers firewall. Their address to the rest of the world is actually the address of the router, not of their physical computer. On their local network they have a different address then what the rest of the world sees, and the router figures out what messages from the outside world need to be sent to the client based on an address translation table.
Given your architecture, this would mean that all clients need to have their routers doing port forwarding, which is of course unfeasible (imagine gtalk or aim requiring users to do port forwarding).
The more common architecture is to have the Server do the work of rebroadcasting messages to the connected clients and maintain tables to lookup whose talking with who. This way there is a single server which will need a static ip (or be port forwarded), and all users are simply clients which connect to the server socket and read messages from it.
For actual code describing the second architecture please see http://pirate.shu.edu/~wachsmut/Teaching/CSAS2214/Virtual/Lectures/chat-client-server.html. Then the machine which is running the server code either needs a static ip or if it is behind a router needs traffic from the port it is listening on to be forwarded.
So on the server code you will bind to the ip assigned from your router (something like 192.168.1.2 at some port say 5000). Then go to your routers configuration page (it may be 192.168.1.1 see http://www.wikihow.com/Port-Forward/Open-Ports-on-a-Linksys-Router), and forward port 5000 to the address 192.168.1.2.
The Interactive Connectivity Establishment (ICE) protocol combines various NAT traversal utilities such as the STUN and TURN protocols in order to offer a powerful mechanism that allows Offer/Answer based protocols such as SIP and XMPP to traverse NATs.
This project provides a Java implementation of the ICE protocol that would be usable by both SIP and XMPP applications. The project also provides features such as socket sharing and support for Pseudo TCP.
ice4j is maintained by the Jitsi community.
ice4j
I first wrote an example Java server and Android client. I want to keep track of the clients that log on to the server. In the socket objects each Android client will have a unique port number and socket IP address where it is connecting from. So these are the options to identify clients from each other.
I decided not to use the port numbers from each client socket because of the small possibility that the randomly selected port numbers for two Android clients could be the same number. A small chance but possible.
Instead I decided to use the IP socket address that is another string of information included in every client socket. Great idea, right? Not so fast.
The functions to use are:
in the server
socket.getRemoteSocketAddress()
and in the client
socket.getLocalSocketAddress()
however when I am using these methods, the returned address is not the same.
if I use getLocaSocketlAddress() on a socket object in the client and send that as a String to the server, then later I have to use getRemoteSocketAddress() on the socket connection in the server and see if it as the same address I received from the client as a string. This is done to identify which client I received the message from. The two address do not match as they are supposed to.
Example, client gets socket address by calling getLocalSocketAddress() on the socket object in client -------> sends address as string in message to server -----> server gets message and calls getRemoteSocketAddress() on socket to select only that client to send message back to. not all the other clients.
The server stores all the sockets of clients that are connected in an ArrayList.
Using getLocalSocketAddress() on the socket for the client side returns for example XXX.XXX.11.17 and if I use getRemoteSocketAddress() in the socket on the server side I get XXX.XXX.0.13, This is messed up, however the port number information matches perfectly if I use getLocalPort() in the client and getPort() in the server.
so it is possible that I can use client port number as a way to reliably identify which client to send a message to.
what is wrong with the getLocalSocketAddress() methods or are they broken? and is there another way to identify between which client has connected to the server?
on the server side, Java swing desktop app
// desktop connected to the internet by eathernet cable
socket = serversocket.accept();
System.out.println("SOCKET ADDRESS: "
+ socket.getRemoteSocketAddress().toString());
on the client side,
// Android tablet connected to internet by wifi
public void run() {
socket = new Socket(InetAddress.getByName(serverIP), 6789);
socketAddress = (socket.getLocalSocketAddress().toString());
Log.i(TAG, "SOCKET ADDRESS: " + socketAddress);
Tracking clients using IP address is a bad idea in general, for several reasons.
First of all, clients can connect through some NAT - in such case the remote address seen by the server is not the same as the address on the client side. Imagine e.g. a setup with ADSL/WiFi router doing NAT - it would (most likely) have one public IP address, WiFi devices would use internal IP addresses, e.g. from 10.0.0.x or 192.168.x.x pool (very popular setup).
Note, that in such a setup several WiFi devices would appear (from the server perspective) to be connecting from the same IP address - the public IP of the router. Obvious implication: the client's IP address is not unique, it's IP/port pair that's unique. To be precise, TCP connections can be uniquely identified by (local IP, local port, remote IP, remote port) tuple.
Last, but not least: client can disconnect and connect again from a different IP address, that's very common in mobile networks (actually in any network where IPs are assigned dynamically).
In your question you wrote:
Example, client gets socket address by calling getLocalSocketAddress()
on the socket object in client -------> sends address as string in
message to server -----> server gets message and calls
getRemoteSocketAddress() on socket to select only that client to send
message back to. not all the other clients.
I don't quite get what you mean by select only that client to send message back to. For each connected client you'd have a separate TCP connection, and separate Socket instance. To send data to a particular client, use a socket associated with this particular client, that's it. You shouldn't care about client's IP/port at all, really, that's the task of TCP/IP protocol stack.
If you really want to identify each connecting device, you have to do it above the TCP/IP, in your application protocol. You simply need to send some unique identifier after connecting. But that's whole different story.
I want Peer(s) to be able to send DatagramPackets over a WIFI LAN for the sole purpose of discovering other Peers. So, I have each Peer made up of a Client(Sending packets) and a Server (listening for packets).
I have only been able to get this to work by using IPConfig on each machine to get their respective IPv4 Address and then using that as a paramter for the creation of the DatagramPacket:-
InetAddress server = InetAddress.getByName("THE IPv4 ADDRESS OF THE PEER'S SERVER
RUNNING ON THE OTHER MACHINE");
DatagramPacket sendPacket = new DatagramPacket(outBuffer, outBuffer.length,
server, serverPort);
Am I using broadcast (for peer discovery) in the right way here because it seems pretty rubbish to me if I am? I was under the assumption I could have a client on machineA fire off a packet into the LAN abyss and the Server running on machineB would be listening to the entire LAN and detect the packet. At the moment all I'm doing is manually using IPConfig on the machine running the server and typing that address in the DatagramPacket on the machine running the client, which just seems pointless.
I can use multicast just fine but I think broadcast is more what I need for peer discovery.
Help appreciated.
That's not really broadcast, since you're giving the server's address, rather than the broadcast address (255.255.255.255, or whatever your local network broadcast address is (like 192.168.1.255, if your network segment is 192.168.1.0/24).
You also may consider that you could have a firewall blocking incoming UDP packets on your server port. You should look at the documentation for DatagramSocket/DatagramPacket to see if there's a magic incantation for binding the server socket properly, or sending the packet from the client properly.
[Edit: How to find the network broadcast]
The network broadcast address can be found once you know the network address, both of which you can tell from your IP and subnet mask. The subnet mask basically shows how much of the address is the network, and how much is the client. (subnet mask is often written as "netmask") An example:
IP: 192.168.1.101
Netmask: 255.255.255.0
Network Address (CIDR): 192.168.1.0/24
Broadcast Address: 192.168.1.255
or:
IP: 10.13.28.55
Netmask: 255.255.0.0
Network: 10.13.0.0/16
Broadcast Address: 10.13.255.255
So essentially, the network address has a bunch of zeroes at the end, and the broadcast address replaces them with ones.
IPv4 Addresses are 32-bit numbers (easiest to think of them as unsigned. If you do the bitwise-AND of your address and the netmask, you get the network address. If you bitwise-OR that with the bitwise-NOT of the netmask, you get the broadcast address (so (addr & netmask) | ~netmask) would get you the local broadcast).
255.255.255.255 (or 0xFFFFFFFF) is the global broadcast address. IP broadcasts don't cross network segments, so it's safe to send to it, though.
Use the broadcast address 255.255.255.255 for both server and client.