I have a server code in Java which I run on my machine and my friend has a client code which runs on his machine. When he enters my IP so as to connect to my server and get the date, connection fails and nothing happens. Note that when I run server and client programs on my own machine and enter localhost as the address, connection is successful and I get the date message correctly. I'm looking for possible errors and problems causing this.
Server code in Java:
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket listener = new ServerSocket(9999);
try {
while (true) {
Socket socket = listener.accept();
try {
PrintWriter out =
new PrintWriter(socket.getOutputStream(), true);
out.println(new Date().toString());
} finally {
socket.close();
}
}
}
finally {
listener.close();
}
}
}
Client code in Java:
import javax.swing.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
public class Client {
public static void main(String[] args) throws IOException {
String serverAddress = JOptionPane.showInputDialog(
"Enter IP Address of a machine that is\n" +
"running the date service on port 9999:");
Socket s = new Socket(serverAddress, 9999);
BufferedReader input =
new BufferedReader(new InputStreamReader(s.getInputStream()));
String answer = input.readLine();
JOptionPane.showMessageDialog(null, answer);
System.exit(0);
}
}
Some routers might isolate computers in different networks. Try it with both computers on Wifi or both wired to the router. Are your IPs on the same network? Can you see your friend's computer on the network? There might also be some security configurations on your router.
Other than that and firewall issue (which you have disabled), the code looks like it should work fine.
Related
I'm trying to make a basic java echo client server app and the textbook I'm reading says I should run the Server.java file first and then the Client.java second. But for some reason VSCode doesn't seem to be doing that. I run my Server.java file and get this which is what I'm expecting:
Simple Echo Server
Waiting for connection.....
And then I go to my Client.java file and run that, but nothing happens there are no errors, it stays at the two lines shown above, I can CTRL+C to terminate the batch job.
I'm expecting it to say this:
Simple Echo Server
Waiting for connection.....
Connected to client
But that's not happening - I am getting no errors though. I don't think it's a problem with my code since it's identical to the textbook's but I'll post it here.
Server.java
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws Exception {
System.out.println("Simple Echo Server");
try (ServerSocket serverSocket = new ServerSocket(6000)) {
System.out.println("Waiting for connection.....");
Socket clientSocket = serverSocket.accept();
System.out.println("Connected to client");
} catch (IOException ex) {
}
}
}
Client.java
import java.io.*;
import java.io.BufferedReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
public class Client {
public static void main(String[] args) throws Exception {
try {
System.out.println("Waiting for connection.....");
InetAddress localAddress = InetAddress.getLocalHost();
try (Socket clientSocket = new Socket(localAddress, 6000);
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()))) {
}
}
catch (IOException ex) {
} // Handle exceptions
}
}
Is it possible that VS code can't run two java files at one time?
EDIT Tried the dual configuration below, but the result is the same, nothing is changing.
It's achievable in VS Code.
Click to create launch.json, keep the default configurations which should be similar to mine in the following picture then add compounds in it:
Turn to the selection box and choose compounds to run by clicking the left green triangle button, you'll get your wanted result:
I am developing a Client-Server application with several other programmers, in Java. At this point in time I do not want to be running the code locally. I want to be able to connect to the Server from any machine.
I wrote a test server and test client, just to make sure that things are working properly. But they are not. I am using Amazon AWS EC2 Linux that comes with Java. I am able to compile and run my Server after I SSH into the EC2, but the Client on my local disk is just not connecting. Here is the code.
// Code found online (https://cs.lmu.edu/~ray/notes/javanetexamples/)
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
public class TestServer {
public static void main(String[] args) throws Exception {
try (ServerSocket listener = new ServerSocket(50000)) {
System.out.println("The capitalization server is running...");
System.out.println(listener.getInetAddress());
ExecutorService pool = Executors.newFixedThreadPool(20);
while (true) {
pool.execute(new Capitalizer(listener.accept()));
}
}
}
private static class Capitalizer implements Runnable {
private Socket socket;
Capitalizer(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
System.out.println("Connected: " + socket);
try {
Scanner in = new Scanner(socket.getInputStream());
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
while (in.hasNextLine()) {
out.println(in.nextLine().toUpperCase());
}
} catch (Exception e) {
System.out.println("Error:" + socket);
} finally {
try { socket.close(); } catch (IOException e) {}
System.out.println("Closed: " + socket);
}
}
}
}
// Code found online (https://cs.lmu.edu/~ray/notes/javanetexamples/)
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
public class TestClient {
public static void main(String[] args) throws Exception {
try (Socket socket = new Socket("ADDRESS HERE", 50000)) {
System.out.println("Enter lines of text then Ctrl+D or Ctrl+C to quit");
Scanner scanner = new Scanner(System.in);
Scanner in = new Scanner(socket.getInputStream());
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
while (scanner.hasNextLine()) {
out.println(scanner.nextLine());
System.out.println(in.nextLine());
}
}
}
}
In place of "ADDRESS HERE" in the Client, I have tried the private IP and public IP of my Amazon EC2 instance. I have also tried the public DNS name. Nothing seems to work. There is just no connection from the Client to the Server. In fact, "Enter lines of text then Ctrl+D or Ctrl+C to quit" never prints.
All help is appreciated. Thank you.
Allow your IP address to send request to the EC2. For this, you need to go to your Security Group and add your IP there. Follow these steps-
GO to your AWS console.
Click on EC2, then under Resources you will find Security Groups.
Select your security group.
Follow the steps in the given image.
Since you're able to connect to EC2 instance via SSH, your Security Group allows this.
Now you need to allow requests from the client in this Security Group. You will either need to provide a concrete IP, IP range or allow all IPs (not recommended) in the group.
You can find how to do this here.
I am creating a Java HTTP server that checks to make sure a client is not banned before redirecting to the main server. I have already created everything for the server that is needed, I just don't know how to redirect to another port that is running the main server. Here is my code:
package netlyaccesscontrol;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class AllowedCheck {
public static void main(String[] args) {
String line = null;
try {
FileReader reader = new FileReader("Banned.txt");
BufferedReader buffer = new BufferedReader(reader);
ServerSocket s = new ServerSocket(80);
Socket c = s.accept();
String clientIP = c.getInetAddress().toString();
while ((line = buffer.readLine()) != null) {
if (clientIP == line) {
s.close();
} else {
// redirect to main server here
}
}
} catch (FileNotFoundException ex) {
System.out.println("The banned IP address file does not exist.");
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
The redirection that you are thinking of is something supported by HTTP and the browsers. There's a specific HTTP response code that tells the caller to redirect and a way to specify it.
Raw sockets are a low-level network protocol that is not going to support redirection as you expect. The most you might be able to do is have this program be a proxy and, upon success, push all incoming data/outgoing responses to/from the ultimate server. But what you have here is by no means going to cut it.
I want to test this simpel server-client application on my own machine at home. How can I run this in Eclipse and then see if the other side can see my message. I want to at some point be able to make a chat window that anyone could have on their machine and send messages to anyone that is online that is linked into the chat window.
But first I have to be able to see that I have a connection. Should I install a server on my computer, or someone told me that there was a server already installed on my computer but I just had to have windows turn it on. (Windows 7)
Question: How can I test this client-server on my computer at home?
Code:
Client Side:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import javax.swing.JOptionPane;
public class DateClient {
public static void main(String[] args) throws IOException {
String serverAddress = JOptionPane.showInputDialog(
"Enter IP Address of a machine that is\n" +
"running the date service on port 9090:");
Socket s = new Socket(serverAddress, 9090);
BufferedReader input =
new BufferedReader(new InputStreamReader(s.getInputStream()));
String answer = input.readLine();
JOptionPane.showMessageDialog(null, answer);
System.exit(0);
}
}
Server side:
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
public class DateServer {
public static void main(String[] args) throws IOException {
ServerSocket listener = new ServerSocket(9090);
try {
while (true) {
Socket socket = listener.accept();
try {
PrintWriter out =
new PrintWriter(socket.getOutputStream(), true);
out.println(new Date().toString());
} finally {
socket.close();
}
}
}
finally {
listener.close();
}
}
}
Code I want to Add for new message:
out.println("Hello Doug, how are you!);
This will not show in my message box when it shows up on the screen. Is 127.0.0.1 always the IP address that needs to be entered when testing from eclipse or how would I change this around so that I could let the user determine their own IP address.
You can just open two terminals. For the DateClient, just use localhost or 127.0.0.1 as the address. If you really must use Eclipse, then you can run one of the program from Eclipse and the other from a terminal.
You don't need any server.
In Eclipse (assuming your coding is correct), you can run multiple programs (Java files with a main method) simultaneously.
First, say DateServer -> Run As -> Java Application
Next, say DateClient -> Run As -> Java Application
To run this, you don't need any additional server, but Win 7 might ask you for permissions to unblock these programs from accessing the network. You should say yes to these permissions.
If you want to get a feel of separate client and server, this might be better
Keep the DateClient and DateServer in two different projects
Compile both projects as JARs
Open two different DOS consoles and run these two applications in these separate DOS consoles.
Client Side :
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
public class ClientSide {
public static void main(String[] args) {
try {
Socket s = new Socket("localhost", 1234);
DataOutputStream dos = new DataOutputStream(s.getOutputStream());
dos.writeUTF("Hello");
} catch (IOException ex) {
System.out.println("Connection failed");
}
}
}
Server Side :
import java.io.DataInputStream;
import java.io.IOException;
import java.net.ServerSocket;
public class ServerSide {
public static void main(String[] args) {
try {
ServerSocket ss = new ServerSocket(1234);
System.out.println("waiting for connection...");
DataInputStream dis = new DataInputStream(ss.accept().getInputStream());
System.out.println("Successfully Connected\n" + dis.readUTF());
} catch (IOException ex) {
System.out.println("Server Not Started : " + ex);
}
}
}
I'm not too sure how to go about getting the external IP address of the machine as a computer outside of a network would see it.
My following IPAddress class only gets the local IP address of the machine.
public class IPAddress {
private InetAddress thisIp;
private String thisIpAddress;
private void setIpAdd() {
try {
InetAddress thisIp = InetAddress.getLocalHost();
thisIpAddress = thisIp.getHostAddress().toString();
} catch (Exception e) {
}
}
protected String getIpAddress() {
setIpAdd();
return thisIpAddress;
}
}
I am not sure if you can grab that IP from code that runs on the local machine.
You can however build code that runs on a website, say in JSP, and then use something that returns the IP of where the request came from:
request.getRemoteAddr()
Or simply use already-existing services that do this, then parse the answer from the service to find out the IP.
Use a webservice like AWS and others
import java.net.*;
import java.io.*;
URL whatismyip = new URL("http://checkip.amazonaws.com");
BufferedReader in = new BufferedReader(new InputStreamReader(
whatismyip.openStream()));
String ip = in.readLine(); //you get the IP as a String
System.out.println(ip);
One of the comments by #stivlo deserves to be an answer:
You can use the Amazon service http://checkip.amazonaws.com
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
public class IpChecker {
public static String getIp() throws Exception {
URL whatismyip = new URL("http://checkip.amazonaws.com");
BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(
whatismyip.openStream()));
String ip = in.readLine();
return ip;
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
The truth is: 'you can't' in the sense that you posed the question. NAT happens outside of the protocol. There is no way for your machine's kernel to know how your NAT box is mapping from external to internal IP addresses. Other answers here offer tricks involving methods of talking to outside web sites.
All this are still up and working smoothly! (as of 10 Feb 2022)
http://checkip.amazonaws.com/
https://ipv4.icanhazip.com/
http://myexternalip.com/raw
http://ipecho.net/plain
http://www.trackip.net/ip
http://bot.whatismyipaddress.com (10 Feb 2022)
http://curlmyip.com/ (17 Dec 2016)
Piece of advice: Do not direcly depend only on one of them; try to use one but have a contigency plan considering others! The more you use, the better!
Good luck!
As #Donal Fellows wrote, you have to query the network interface instead of the machine. This code from the javadocs worked for me:
The following example program lists all the network interfaces and their addresses on a machine:
import java.io.*;
import java.net.*;
import java.util.*;
import static java.lang.System.out;
public class ListNets {
public static void main(String args[]) throws SocketException {
Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();
for (NetworkInterface netint : Collections.list(nets))
displayInterfaceInformation(netint);
}
static void displayInterfaceInformation(NetworkInterface netint) throws SocketException {
out.printf("Display name: %s\n", netint.getDisplayName());
out.printf("Name: %s\n", netint.getName());
Enumeration<InetAddress> inetAddresses = netint.getInetAddresses();
for (InetAddress inetAddress : Collections.list(inetAddresses)) {
out.printf("InetAddress: %s\n", inetAddress);
}
out.printf("\n");
}
}
The following is sample output from the example program:
Display name: TCP Loopback interface
Name: lo
InetAddress: /127.0.0.1
Display name: Wireless Network Connection
Name: eth0
InetAddress: /192.0.2.0
From docs.oracle.com
Make a HttpURLConnection to some site like www.whatismyip.com and parse that :-)
How about this? It's simple and worked the best for me :)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
public class IP {
public static void main(String args[]) {
new IP();
}
public IP() {
URL ipAdress;
try {
ipAdress = new URL("http://myexternalip.com/raw");
BufferedReader in = new BufferedReader(new InputStreamReader(ipAdress.openStream()));
String ip = in.readLine();
System.out.println(ip);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
http://jstun.javawi.de/ will do it - provided your gateway device does STUN )most do)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
import java.util.regex.Pattern;
public class ExternalIPUtil {
private static final Pattern IPV4_PATTERN = Pattern.compile("^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])$");
private static final String[] IPV4_SERVICES = {
"http://checkip.amazonaws.com/",
"https://ipv4.icanhazip.com/",
"http://bot.whatismyipaddress.com/"
// and so on ...
};
public static String get() throws ExecutionException, InterruptedException {
List<Callable<String>> callables = new ArrayList<>();
for (String ipService : IPV4_SERVICES) {
callables.add(() -> get(ipService));
}
ExecutorService executorService = Executors.newCachedThreadPool();
try {
return executorService.invokeAny(callables);
} finally {
executorService.shutdown();
}
}
private static String get(String url) throws IOException {
try (BufferedReader in = new BufferedReader(new InputStreamReader(new URL(url).openStream()))) {
String ip = in.readLine();
if (IPV4_PATTERN.matcher(ip).matches()) {
return ip;
} else {
throw new IOException("invalid IPv4 address: " + ip);
}
}
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.out.println("IP: " + get());
}
}
Get from multiple IP services concurrently such as:
http://checkip.amazonaws.com/
https://ipv4.icanhazip.com/
http://bot.whatismyipaddress.com/
and so on ...
and ExecutorService.invokeAny(tasks) return the result of the first successfully thread. Other tasks that have not completed will be cancelled.
It's not that easy since a machine inside a LAN usually doesn't care about the external IP of its router to the internet.. it simply doesn't need it!
I would suggest you to exploit this by opening a site like http://www.whatismyip.com/ and getting the IP number by parsing the html results.. it shouldn't be that hard!
If you are using JAVA based webapp and if you want to grab the client's (One who makes the request via a browser) external ip try deploying the app in a public domain and use request.getRemoteAddr() to read the external IP address.
System.out.println(pageCrawling.getHtmlFromURL("http://ipecho.net/plain"));
An alternative solution is to execute an external command, obviously, this solution limits the portability of the application.
For example, for an application that runs on Windows, a PowerShell command can be executed through jPowershell, as shown in the following code:
public String getMyPublicIp() {
// PowerShell command
String command = "(Invoke-WebRequest ifconfig.me/ip).Content.Trim()";
String powerShellOut = PowerShell.executeSingleCommand(command).getCommandOutput();
// Connection failed
if (powerShellOut.contains("InvalidOperation")) {
powerShellOut = null;
}
return powerShellOut;
}