SignalR java cannot connect to server - java

I'm having trouble connecting my java application to my SignalR Server.
The server is very simple and can be found here:
https://code.msdn.microsoft.com/windowsdesktop/Using-SignalR-in-WinForms-f1ec847b
I can connect web clients(javascript) and windows clients (C#) but I'm having trouble with my java client.(https://github.com/SignalR/java-client)
Here is my code so far:
package javaapplication2;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import microsoft.aspnet.signalr.client.SignalRFuture;
import microsoft.aspnet.signalr.client.hubs.HubConnection;
import microsoft.aspnet.signalr.client.hubs.HubProxy;
public class JavaApplication2 {
public static void main(String[] args) throws IOException, InterruptedException, ExecutionException, TimeoutException
{
String ServerURI = "http://localhost:8080/signalr";
HubConnection Connection = new HubConnection(ServerURI);
HubProxy HubProxy = Connection.createHubProxy("MyHub");
HubProxy.on("AddMessage", () -> { System.out.println("Some message"); });
Connection.error(new ErrorCallback() {
#Override
public void onError(Throwable error) {
error.printStackTrace(); //<==SocketException
}
});
SignalRFuture<Void> con =Connection.start();
con.get();
}
}
Update
When I run it I get a "ExecutionException: java.net.SocketException: Connection reset"
Exception in thread "main" java.util.concurrent.ExecutionException: java.net.SocketException: Connection reset
at microsoft.aspnet.signalr.client.SignalRFuture.get(SignalRFuture.java:112)
at microsoft.aspnet.signalr.client.SignalRFuture.get(SignalRFuture.java:102)
at javaapplication2.JavaApplication2.main(JavaApplication2.java:27)
Caused by: java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:209)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:286)
at java.io.BufferedInputStream.read(BufferedInputStream.java:345)
at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:704)
at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:647)
at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:675)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1535)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1440)
at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)
at microsoft.aspnet.signalr.client.http.java.NetworkRunnable.run(NetworkRunnable.java:72)
at java.lang.Thread.run(Thread.java:745)
-If I change "localhost" to something that does not exist ( e.g locahostX) I get a java.net.UnknownHostException
-If If change "localhost" to my IP I don't event get an exception...
-All the other apps work with both (localhost or IP)
At first I thought it was a firewall issue but it wasn't that...
Obviously I'm missing something...
Any ideas?
Thanks

It turns out that I had to use an overload of start,the one that takes as a parameter a ClientTransport object
public SignalRFuture<Void> start(ClientTransport transport)
If anyone has an explanation why the parameterless start method fails ,please post it as an answer and I will mark it as the solution.
Here is a full example that works:
package javaapplication2;
import java.io.IOException;
import java.util.Scanner;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import microsoft.aspnet.signalr.client.SignalRFuture;
import microsoft.aspnet.signalr.client.hubs.HubConnection;
import microsoft.aspnet.signalr.client.hubs.HubProxy;
import microsoft.aspnet.signalr.client.transport.ServerSentEventsTransport;
import microsoft.aspnet.signalr.client.hubs.SubscriptionHandler2;
public class JavaApplication2 {
public static void main(String[] args) throws IOException, InterruptedException, ExecutionException, TimeoutException
{
String ServerURI = "http://localhost:8080/signalr";
HubConnection Connection = new HubConnection(ServerURI);
HubProxy HubProxy = Connection.createHubProxy("MyHub");
HubProxy.on("AddMessage", new SubscriptionHandler2<String, String>() {
#Override
public void run(String e1, String e2) {
System.out.println(e1.toString()+ " -> " +e2.toString());
}
}, String.class, String.class);
SignalRFuture<Void> con =Connection.start(new ServerSentEventsTransport(Connection.getLogger())); //Or LongPollingTransport
con.get();
Scanner inputReader = new Scanner(System.in);
String line = inputReader.nextLine();
while (!"exit".equals(line)) {
HubProxy.invoke("send", "Console", line);
line = inputReader.next();
}
inputReader.close();
Connection.stop();
}
}

If I change "localhost" to something that does not exist ( e.g
locahostX) I get a java.net.UnknownHostException
Are you sure about this?
On the server command prompt run "ipconfig" to get the IP address of the server.
From the client command prompt type "ping " + IP address of the server.
If the ping sends packages, then try to put the IP in the string "ServerURI" to be something like "http://"+ServerIP+":8080/signalr".

Related

Simple SocketHandler for java8 logging(java.util.logging) throws ConnectionException

The intention is to stream the log during runtime on a specific host:port, so that the logs are accessible to users outside the running system, from browser.
As you can see, i have created a simple SocketHandler for java8 logging(java.util.logging), is there something that i have missed?
import java.net.MalformedURLException;
import java.net.URL;
import java.io.IOException;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.logging.SocketHandler;
import java.util.logging.XMLFormatter;
public class Main {
public static void main(String[] args) throws Exception {
Logger logger = Logger.getLogger("concrete.log");
SocketHandler handler = new SocketHandler("HOSTNAME", 19004);
LogRecord logRec = new LogRecord(Level.INFO, "Log recorded");
handler.publish(logRec);
handler.setFormatter(new XMLFormatter());
logger.addHandler(handler);
logger.info("socket handler info message");
}
}
When i run the code, i see the following exception, i have tried checking the system firewall settings on both local(mac/windows) and remote(Linux) and seen that the settings do not block 19004 port
Exception in thread "main" java.net.ConnectException: Connection refused (Connection refused)
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:476)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:218)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:200)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:394)
at java.net.Socket.connect(Socket.java:606)
at java.net.Socket.connect(Socket.java:555)
at java.net.Socket.<init>(Socket.java:451)
at java.net.Socket.<init>(Socket.java:228)
at java.util.logging.SocketHandler.connect(SocketHandler.java:167)
at java.util.logging.SocketHandler.<init>(SocketHandler.java:154)
at Main.main(Main.java:16)
UPDATE
As suggested by bosowski
When i create Socket to listen to a specific port, the log messages are getting printed on the console of the host. However, am unable to access hostname:port for the log to be streamed from the browser. Is there anything specific that needs to be performed after this step?
Please let me know
import java.io.*;
import java.net.*;
public class MyServer {
public static void main(String[] args)
{
try {
ServerSocket ss = new ServerSocket(19004);
Socket soc = ss.accept();
DataInputStream dis
= new DataInputStream(soc.getInputStream());
String str = (String)dis.readUTF();
System.out.println("message= " + str);
ss.close();
}
catch (Exception e) {
System.out.println(e);
}
}
}
SocketHandler does not open up a port to connect to, if that's what you're assuming. It tries to connect to the specified host and port, so you need to have a port that is listening on the host that you are trying to connect to.
https://docs.oracle.com/javase/8/docs/api/java/util/logging/SocketHandler.html#SocketHandler-java.lang.String-int-
<handler-name>.host specifies the target host name to connect to (no default).
<handler-name>.port specifies the target TCP port to use (no default).
If you do indeed have a listening TCP port on the hostname that you're trying to connect to, you can try running sudo nmap -F hostname to check if the port is indeed accessible from your machine.

Running a live Java Server on Amazon AWS

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.

Java Socket Connection Failure

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.

RMI programme: Client side giving Error

I am creating RMI program for my class assignment in Netbeans. It is a simple RMI program and The server side is working properly. But as I run my client side file. It ends up giving me error
Exception in thread "main" java.security.AccessControlException: access denied ("java.net.SocketPermission" "127.0.0.1:1099" "connect,resolve")
plus it is saying some error at line 26 at client code.
For clear understanding I am giving full code of all three files.
Interface.java :
package RMI;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface DemoInterface extends Remote {
public String SayDemo() throws RemoteException;
}
Server.java
package RMI;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
public class Server implements Interface{
public Server()
{
super();
}
private String message;
public Server(String msg) throws RemoteException
{
message = msg;
}
public static void main(String[] args) {
try {
DemoInterface h = new Server("Hello");
DemoInterface stub = (DemoInterface) UnicastRemoteObject.exportObject(h,0);
LocateRegistry.createRegistry(4096);
Registry registry = LocateRegistry.getRegistry("127.0.0.1",4096);
registry.rebind("Hello", stub);
System.out.println("Server is connected and ready to use");
}
catch(Exception e)
{
System.out.println("server not connected\n"+e);
}
}
#Override
public String SayDemo() throws RemoteException {
System.out.println("Server.saydemo override");
return message;
}
}
Client.java
package RMI;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class Client {
public static void main(String[] args) {
if(System.getSecurityManager() == null)
{
System.setSecurityManager(new SecurityManager());
}
try {
Registry reg = LocateRegistry.getRegistry("127.0.0.1", 4096);
System.out.println("in try after reg locate");
DemoInterface h = (DemoInterface) reg.lookup("Hello");//Error Showed on this line by netbeans
System.out.println(h.SayDemo());
}
catch(RemoteException | NotBoundException e)
{
System.out.println(""+e );
}
}
}
please guide me where I am wrong. Thank You in advance.
You set a SecurityManager in your client main method. Did you also provide a security policy file? The default policy is not very permissive, and denies, among other things, Socket operations.
You can specify a policy that allows all permissions to all code bases like so.
grant {
permission java.security.AllPermission;
};
add it to your command line for invoking java. Substitute mypolicy for your policy file and SomeApp for your main class. Note the two = characters in the second argument
java -Djava.security.manager -Djava.security.policy==mypolicy SomeApp
Note that this is not a safe policy to run for RMI in a production environment (RMI can load remote code bases).
Proper use of the SecurityManager class and policy configuration is a complex topic, for further reading I suggest Java SE 7 Security Documentation and in particular Default Policy Implementation and Policy File Syntax

Getting the 'external' IP address in Java

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;
}

Categories

Resources