I have a very basic understanding of clients, servers, sockets, input and output streams, etc. related to having servers. However, my socket that I created does not seem to work. I used many unused ip and ports, and even tried my own computer's ip. The Socket I created does not throw an IOException, or break anything. Anything past the creation of my socket object never happens.
public class ClientHello {
public static void main(String [] args) {
String ip = "91.202.240.208";
int port = 51678;
try {
System.out.println("1");
Socket sock = new Socket(ip, port);
System.out.println("2");
DataOutputStream stream1 = (DataOutputStream) sock.getOutputStream();
stream1.writeUTF("Hi server!");
DataInputStream stream2 = (DataInputStream) sock.getInputStream();
System.out.println(stream2.readUTF());
sock.close();
}catch(IOException e) {
e.printStackTrace();
}
}
}
Additionally, the ip and port is from a random Ukrainian thingy.
For the IP and port in Socket, you need to put the server socket's IP address and port so it can connect to server. Not just some random IP address.
You need to make a ServerSocket for your server first, and then with the Server's IP and port (you can specify the port when you make sever socket, and ip will be your IP)
and then you that code to connect to server.
Related
I'm using Java's DatagramSocket to send UDP messages from Java to a specific port on my localhost. I listen to this port with netcat: nc -ul 9122.
On the first run of my Java code (after starting nc) - the message is received and displayed on my shell. On each other run - messages are not received. Only restarting nc will do.
This is my Java code:
public static void main(String[] args) throws IOException, InterruptedException {
byte[] buf = "Hi There\n".getBytes();
InetAddress address = InetAddress.getLocalHost();
DatagramPacket packet = new DatagramPacket(buf, buf.length, address, 9122);
DatagramSocket datagramSocket = new DatagramSocket();
datagramSocket.connect(InetAddress.getLocalHost(), 9122);
if(datagramSocket.isConnected()) {
datagramSocket.send(packet);
Thread.sleep(500);
datagramSocket.send(packet);
Thread.sleep(500);
datagramSocket.send(packet);
}
}
What do I miss?
Thanks
This seems to be a feature of ncat. After receiving one UDP packet, it only accepts packets from the same origin host and port. It is similar to a connection: an instance of ncat only handles packets from a single client.
When you start the Java program, it will select an arbitrary local port, and when you restart it you will get a different port. You can set fixed local port by passing it to the DatagramSocket constructor:
DatagramSocket datagramSocket = new DatagramSocket(12345);
I connect via MS Telnet which is where I see the output.
I know 0:0:0:0:0:0:0:0 would be ALL or wildcard...
but where does it come up with 0:0:0:0:0:0:0:1 ?
What's the point of giving me this? Why not give me an IP such as 127.0.0.1?
Is this a virtual MAC address? Javadoc wasn't very informative.
public InetAddress getInetAddress() Returns the address to which the
socket is connected. If the socket was connected prior to being
closed, then this method will continue to return the connected address
after the socket is closed.
Returns: the remote IP address to which this socket is connected, or
null if the socket is not connected.
From https://docs.oracle.com/javase/7/docs/api/java/net/Socket.html#getInetAddress()
MAIN:
public static void main(String[] args) throws IOException {
/*
* The actual work of the server socket is performed by an instance
* of the {#code SocketImpl} class.
*/
// Open a port to accept connections on 8080
ServerSocket srvrSocket = new ServerSocket(8080);
// Block until someone connects
while (true) {
Socket socket = srvrSocket.accept();
handle(socket);
}
}
private static void handle(Socket socket) throws IOException {
try(
socket;
InputStream is = socket.getInputStream();
OutputStream os = socket.getOutputStream();
) {
// Print welcome
DataUtil.writeStringAsInts(os, socket.getInetAddress().toString());
.
.
.
IPV6 has representation of 0:0:0:0:0:0:0:1 for localhost, when we try to connect server socket from local, we may get 0:0:0:0:0:0:0:1 sometimes we may get ::1
The localhost (loopback) address, 0:0:0:0:0:0:0:1, and the IPv6
unspecified address, 0:0:0:0:0:0:0:0, are reduced to ::1 and ::,
respectively
https://en.wikipedia.org/wiki/IPv6_address
The server looks like this(Simplified)
ServerSocket serverSocket = new ServerSocket(port);
Socket clientSocket = serverSocket.accept();
PrintWrite out = new PrintWriter(clientSocket.getOutputStream(), true);
out.println("42");
The client looks like this(Simplified)
Socket clientSocket = new Socket("My public IP",port);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String data;
while(true){
if((data = in.readLine()) != null){
System.out.println(data);
break;
}
}
Additional settings/actions:
Open firewall on servermachine for incoming traffic on the port in question.
Forwarding port in router to private IP of servermachine(192.168.x.x).
Get the public IP to the server by searching for it on www.whatismyip.com
This Question became an answer and now describes the setup for sending the answer to the ultimate question of life, the universe, and everything through cyberspace.
If your server is behind a NAT, you have to setup port forwarding in your router. Opening a port is not enough.
What is the local address of the machine with the server? On which port does your server run? Some ports might be blocked by ISP (for example port 25 is often blocked to prevent spam, some ISPs block common P2P ports).
I want to do UDP Hole Punching with two clients with the help of a server with a static IP. The server waits for the two clients on port 7070 and 7071. After that it sends the IP address and port to each other. This part is working fine. But I'm not able to establish a communication between the two clients. I tried the code in different Wifi networks and in 3G mobile network. The client program throws the IO-Exception "No route to host".
The client code is used for both clients. Once executed with port 7070 and once with 7071.
Do you think I've implemented the UDP hole punching concept correctly? Any ideas to make it work?
Here's the server code first, followed by the client code.
Thank you for help.
Code of server:
public class UDPHolePunchingServer {
public static void main(String args[]) throws Exception {
// Waiting for Connection of Client1 on Port 7070
// ////////////////////////////////////////////////
// open serverSocket on Port 7070
DatagramSocket serverSocket1 = new DatagramSocket(7070);
System.out.println("Waiting for Client 1 on Port "
+ serverSocket1.getLocalPort());
// receive Data
DatagramPacket receivePacket = new DatagramPacket(new byte[1024], 1024);
serverSocket1.receive(receivePacket);
// Get IP-Address and Port of Client1
InetAddress IPAddress1 = receivePacket.getAddress();
int port1 = receivePacket.getPort();
String msgInfoOfClient1 = IPAddress1 + "-" + port1 + "-";
System.out.println("Client1: " + msgInfoOfClient1);
// Waiting for Connection of Client2 on Port 7071
// ////////////////////////////////////////////////
// open serverSocket on Port 7071
DatagramSocket serverSocket2 = new DatagramSocket(7071);
System.out.println("Waiting for Client 2 on Port "
+ serverSocket2.getLocalPort());
// receive Data
receivePacket = new DatagramPacket(new byte[1024], 1024);
serverSocket2.receive(receivePacket);
// GetIP-Address and Port of Client1
InetAddress IPAddress2 = receivePacket.getAddress();
int port2 = receivePacket.getPort();
String msgInfoOfClient2 = IPAddress2 + "-" + port2 + "-";
System.out.println("Client2:" + msgInfoOfClient2);
// Send the Information to the other Client
// /////////////////////////////////////////////////
// Send Information of Client2 to Client1
serverSocket1.send(new DatagramPacket(msgInfoOfClient2.getBytes(),
msgInfoOfClient2.getBytes().length, IPAddress1, port1));
// Send Infos of Client1 to Client2
serverSocket2.send(new DatagramPacket(msgInfoOfClient1.getBytes(),
msgInfoOfClient1.getBytes().length, IPAddress2, port2));
//close Sockets
serverSocket1.close();
serverSocket2.close();
}
Code of client
public class UDPHolePunchingClient {
public static void main(String[] args) throws Exception {
// prepare Socket
DatagramSocket clientSocket = new DatagramSocket();
// prepare Data
byte[] sendData = "Hello".getBytes();
// send Data to Server with fix IP (X.X.X.X)
// Client1 uses port 7070, Client2 uses port 7071
DatagramPacket sendPacket = new DatagramPacket(sendData,
sendData.length, InetAddress.getByName("X.X.X.X"), 7070);
clientSocket.send(sendPacket);
// receive Data ==> Format:"<IP of other Client>-<Port of other Client>"
DatagramPacket receivePacket = new DatagramPacket(new byte[1024], 1024);
clientSocket.receive(receivePacket);
// Convert Response to IP and Port
String response = new String(receivePacket.getData());
String[] splitResponse = response.split("-");
InetAddress ip = InetAddress.getByName(splitResponse[0].substring(1));
int port = Integer.parseInt(splitResponse[1]);
// output converted Data for check
System.out.println("IP: " + ip + " PORT: " + port);
// close socket and open new socket with SAME localport
int localPort = clientSocket.getLocalPort();
clientSocket.close();
clientSocket = new DatagramSocket(localPort);
// set Timeout for receiving Data
clientSocket.setSoTimeout(1000);
// send 5000 Messages for testing
for (int i = 0; i < 5000; i++) {
// send Message to other client
sendData = ("Datapacket(" + i + ")").getBytes();
sendPacket = new DatagramPacket(sendData, sendData.length, ip, port);
clientSocket.send(sendPacket);
// receive Message from other client
try {
receivePacket.setData(new byte[1024]);
clientSocket.receive(receivePacket);
System.out.println("REC: "
+ new String(receivePacket.getData()));
} catch (Exception e) {
System.out.println("SERVER TIMED OUT");
}
}
// close connection
clientSocket.close();
}
UPDATE
The code is generally working. I've tried it in two different home networks now and it's working. But it isn't working in my 3G or university network. In 3G, I verified that the NAT is mapping the two ports (the client port and by the router assigned port) together again, even after closing and opening the clientSocket. Has anyone an idea why it isn't working then?
UDP hole punching can't be achieved with all types of NAT. There is no universal or reliable way defined for all types of NAT. It is even very difficult for symmetric NAT.
Depending on the NAT behaviour, the port mapping could be different for different devices sending the UDP packets.
Like, If A sends a UDP packet to B, it may get some port like 50000. But if A sends a UDP packet to C, then it may get a different mapping like 50002. So, in your case sending a packet to server may give a client some port but sending a packet to other client may give some other port.
You shall read more about NAT behaviour here:
https://www.rfc-editor.org/rfc/rfc4787
https://www.rfc-editor.org/rfc/rfc5128
UDP hole punching not going through on 3G
For symmetric NAT (3G network connecting to a different mobile network), you need to do Multi-UDP hole punching.
See:
https://drive.google.com/file/d/0B1IimJ20gG0SY2NvaE4wRVVMbG8/view?usp=sharing
http://tools.ietf.org/id/draft-takeda-symmetric-nat-traversal-00.txt
https://www.goto.info.waseda.ac.jp/~wei/file/wei-apan-v10.pdf
http://journals.sfu.ca/apan/index.php/apan/article/view/75/pdf_31
Either that or relay all the data through a TURN server.
You rightly use a rendezvous server to inform each node of the others IP / port based on the UDP connection. However using the public IP and port which is the combination which will is obtained by the connection as you have, means that in scenarios where both hosts exist on the same private network hairpin translation is required by the NAT which is sometimes not supported.
To remedy this you can send the IP and port your node believes itself to have in the message to the server (private ip / port) and include this in the information each node receives on the other. Then attempt a connection on both the public combination (the one you are using) and the one I just mentioned and just use the first one which is successfully established.
I've very new to networking and using networks to send messages through programming. Anyways, I have a client and server java command line application (server is running in a VM on the same machine with a bridged network adapter, and host to guest pinging works and vice versa), and it would appear on the server side that each message it receives is coming from a different port. Is this normal behavior? What happens when the machine runs out of ports to use? Does Java's libraries intelligently close the ports after it's done with them?
So basically, is this even a problem? If it is, how do I go about fixing it? Output from the server and then code for the client listed below.
SERVER OUTPUT AFTER SENDING SOME MESSAGES:
Received (/192.168.1.122:59628): shsfh
Received (/192.168.1.122:59629): dfsh
Received (/192.168.1.122:59631): dfh
Received (/192.168.1.122:59632): fdshdf
Received (/192.168.1.122:59633): shf
Received (/192.168.1.122:59637): fgfggsdfhsfdh
Received (/192.168.1.122:59638): fdshf
Received (/192.168.1.122:59639): hs
Received (/192.168.1.122:59640): hfh
CODE FOR THE CLIENT THAT SENT THOSE MESSAGES:
import java.io.*;
import java.util.*;
import java.net.*;
class TCPClient
{
public static void main(String argv[]) throws Exception
{ Scanner scan = new Scanner(System.in);
while (true)
{
String msgcont = scan.nextLine();
System.out.println(tcpSend("192.168.1.153", 6789, 5000, msgcont));
}
}
public static String tcpSend(String ip, int port, int timeout, String content)
{
String ipaddress = ip;
int portnumber = port;
String sentence;
String modifiedSentence;
Socket clientSocket;
try
{
clientSocket = new Socket(ipaddress, portnumber);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
outToServer.writeBytes(content + '\n');
clientSocket.setSoTimeout(timeout);
modifiedSentence = inFromServer.readLine();
clientSocket.close();
outToServer.close();
inFromServer.close();
}
catch (Exception exc)
{
modifiedSentence = "";
}
return modifiedSentence;
}
}
Yes, everytime you open a socket to other host, the connection can be initiated from any of the remaining port on your machine. The OS chooses the next available port and makes the connection.
There are 65536 open ports available from which first 1-1024 ports are reserved by the system.