a bizarre Connection refused: connect error in Java client - java

I have encountered the following error:
java.net.ConnectException: Connection refused: connect
I'll show some code below but first, a description because it baffles me. I wrote a very basic chat program that can act as either a server or client depending on the initial button you press (host or connect). Tested on both localhost and over the internet with friends, works perfectly, as intended. I've started writing a second software and using almost the same code, but having more classes, I get this error when trying to connect to a host of the same program. So, prog A can connect to prog A fine, but B cannot connect to B. One might assume firewall issues, but here's the plot twist: B can connect to A and A can connect to B again perfectly. But B cannot connect to another copy of itself. I used the official oracle tutorials for TCP and worked perfectly on the chat program referred to as A. Depending on the press of a button, A will run one of its main class' methods (to start a server or client). B on the other hand, will create a new object of a class, either a Host
public class Host
{
static ServerSocket serverSocket = null;
static Socket clientSocket = null;
static PrintWriter out = null;
static BufferedReader in = null;
static String inputLine;
public Host() throws IOException
{
serverSocket = new ServerSocket(4444);
System.out.println("Server created, waiting for guest.");
clientSocket = serverSocket.accept();
System.out.println("Guest connected.");
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
while ((inputLine = in.readLine()) != null)
{
//if (inputLine.equals("q")) {break;}
System.out.println("Message recieved:" + inputLine);
}
}
}
or a Guest
public class Guest
{
static Socket socket = null;
static PrintWriter out;
static BufferedReader in = null;
static String inputLine;
public Guest() throws IOException
{
System.out.println("Connecting to host");
try
{socket = new Socket("localhost", 4444);
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
}
catch (UnknownHostException err) {System.out.println("unknown host"); System.exit(3);}
catch (IOException err) {System.out.println(err); /*System.exit(4);*/}
System.out.println("Connected to host");
while ((inputLine = in.readLine()) != null)
{
//if (inputLine.equals("q")) {break;}
System.out.println("Message recieved:" + inputLine);
}
}
}
I have the proper imports, I just didn't paste them here. Both programs try to connect to localhost and only A works, this other one does not. Again, creating a Guest, I can connect to the chatprogram's server. A chatprogram client can connect to this server. But this client cannot connect to this server.
Has anyone experienced anything similar? Is there an obvious solution, something I'm missing? I'm really clueless here, I literally copy/pasted server/client codes.
Edit: stack trace.
java.net.ConnectException: Connection refused: connect
at java.net.DualStackPlainSocketImpl.connect0(Native Method)
java.net.ConnectException: Connection refused: connect
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:69)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:157)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:391)
at java.net.Socket.connect(Socket.java:579)
at java.net.Socket.connect(Socket.java:528)
at java.net.Socket.<init>(Socket.java:425)
at java.net.Socket.<init>(Socket.java:208)
at mainPack.Guest.<init>(Guest.java:21)
at mainPack.GameStarter.grandMain(GameStarter.java:101)
at mainPack.GameStarter.<init>(GameStarter.java:27)
at mainPack.GameStarter.main(GameStarter.java:34)

In your Host, you only accept one connection, and then the server stops listening. If something is tying up that connection, nothing else would be able to connect to the Host. An accepted connection should immediately be delegated to another thread for processing so that the Host can loop and listen on the server socket again. See "Supporting Multiple Clients" in the Socket tutorial.

Remove your static declarations from the variables in Guest. Same for Host (although if you have only one host it should be ok).
Update
e.g. pseudo-code
create server socket
while true (or quit received) {
accept connection
spawn thread to handle communication
}

Need more details as to how this is being run and what the error is exactly (I suspect client returns a network-level connect error when attempting to reach the host) but in general there is only one port being used: 4444. I presume the error (not posted) is that this port is in use by the first programs that are communicating on that port on the same machine.
Further, the static references only allow one instance of the various sockets to exist in a given JVM at a time. These cannot be concurrently used by multiple threads possibly implemented by other client classes using these same (one) static resources.

Related

Android dealing with IoT devices with NO Internet connection

I'm trying to build a project where I must pilot an IoT device from smartphone via Wifi.
This device has the SPWF01 Wifi Module integrated, and is configured as an access point (that has no Internet access) with security type WEP. On this access point configuration we also have a TCP Socket Server that intercepts smartphone communications.
On the smartphone side, we have the part which scans and connects to our device's access point(which works, although i get the esclamation point on the wifi icon since it has no Internet access). After we've connected, we start the Client Socket which connects to the server on our IoT device(the ip address of the server socket is actually the gateway of the access point). And here is where the trouble starts, because the client socket won't start. Here is the code:
public void SocketInit(String ip, int port) throws IOException {
InetAddress addr = InetAddress.getByName(ip);
SocketAddress sockaddr = new InetSocketAddress(addr, port);
nsocket = new Socket();
nsocket.setReuseAddress(true);
nsocket.setTcpNoDelay(false);
nsocket.setReceiveBufferSize(700); //Must be less than 730byte witch is the module buffer
nsocket.setSendBufferSize(700);
nsocket.connect(sockaddr, 5000); //5 second connection timeout
}
And here is the exception i get:
java.net.SocketException: socket failed: ENONET (Machine is not on the network)
And I get that error even before reaching nsocket.connect(), precisely on setReuseAddress.
Since the exception I get is ENONET, I thought that it must be because the access point has no internet access so I used the solution proposed here for testing purpose:
adb shell settings put global captive_portal_detection_enabled 0
This is a solution that can't be done programmatically without having root access, but I wanted to test if that was the problem. But although the exclamation mark on the wifi icon had disappeared, the client socket still gave me the same exception error.
Does anybody have a solution for this behaviour? Thank you in advance!
Sometimes the client socket manages to open, with a success rate of 1 out of 20 times. But when it does, i usually get another exception after a couple of messages sent:
java.net.SocketException: recvfrom failed: ECONNRESET (Connection reset by peer)
Here is the code I used to connect to the access point from the smartphone:
WifiConfiguration wc=new WifiConfiguration();
wc.SSID= host;
wc.status = WifiConfiguration.Status.ENABLED;
wc.priority = 40;
wc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
wc.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
wc.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
wc.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
wc.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
wc.allowedGroupCiphers.clear();
wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
wc.wepKeys[0] = password;
wc.wepTxKeyIndex = 0;
int netId = mainWifi.addNetwork(wc);
try {
//mainWifi.setWifiEnabled(true);
mainWifi.disconnect();
mainWifi.enableNetwork(netId, true);
mainWifi.reconnect();
startConnectionCheck = true;
System.out.println("enabled network");
} catch (Exception e) {
e.printStackTrace();
System.out.println(e.getMessage());
}
The access point's security type is WEP. That is because the Wifi module can't implement WPA.
Tests done on Marshmallow.
I am not 100% certain if this issue is the same.
I had to do a project a whileback and used Java sockets.
When doing intial testing, I used the local loopback and used ports on the same computer and multiple threads. Eventually it worked well enough to test between two computers. I found it didn't work between two computers. After turning off all my firewalls and protections etc on the network and getting desperate enough to use direct connection ethernet cables, I figured out the issue.
Sockets cares which gateway you use. The solution was for me to use the gateway rather than the loopback... It is obvious looking back now...
Anyway, it is likely that your mobile gateway, wifi gateway, and local loopback are all different.
Here is an ugly code blurbe that I hope gives direction with very little inspiration...
Socket socket = null;
try {
socket = new Socket(ip, port, InetAddress.getLoopbackAddress(), localServerPort);
}
catch (Exception e) {
}
if (socket == null) {
try {
socket = new Socket(ip, port, InetAddress.getLocalHost(), localServerPort);
}
catch (Exception e) {
}
}
if(socket == null) {
throw new Exception("Neither the loop back nor the host could find this sucker.");
}

Java webserver blocks connections on PC

At this point, I am testing a webserver client/host system to be run on my raspberry pi (host) and on my pc (client). The basic idea is that every 5 seconds, the client on my pc sends a message to the host located at "192.168.0.11" at port 7051. It processes it and sends a message back to my pc.
For this I am using the following client code:
public static String getData() throws Exception {
try {
Socket socket = new Socket(SERVER_ADDRESS, SERVER_PORT);
socket.setReuseAddress(true);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
int msg = 71;
out.write("TEALBEE_CUR:" + msg);
out.flush();
String input;
String data = "";
while ((input = in.readLine()) != null) {
data += input;
}
socket.close();
return data;
} catch (Exception e) {
e.printStackTrace();
System.exit(-1);
}
return null;
}
The problem here is that while data-flow is consistent and can run for at least a week; I lost use of other sockets connections on my pc, namely my Kodi remote control (this is media centre which I can control through a socket connection on my smartphone). My pc at address "192.168.0.37" accepts connections at port 193 for Kodi but after running the Java client for some time and sending a lot of requests to the server, I notice that the remote cannot connect anymore to my PC.
I thought that this might be the case because the sockets cannot be reused and after a single use the socket becomes unusable. This does seem to be the case as my host detects a different socket port for each request.
I tried to solve this by adding the code socket.setReuseAddress(true) and properly closing the socket after each message, but the problem still occurs.
How can I fix this properly (if possible only use one client socket and close this properly so it can be used again the next time).
EDIT: also important to note I can access 192.168.0.37:193 from my PC, but not from my smartphone when the socket connection cannot be established. Yes I am sure that the PC and smartphone and RPI are on the same network and without the client program running I CAN access 192.168.0.37:193 from my smartphone.

Java: Specifying the local address for an outgoing connection

We've many servers which host multiple IP addresses. The additional ones are so-called Virtual IPs ("VIPs").
We'd like to enable a Java app to make an outgoing connection which lists as source address a designated Virtual IP rather than the host ip address.
Here's what we've tried. The ip address listed in InetAddress#getByAddress is the virtual ip address. The property url is a user-specified target url to connect to.
public void attemptConnection() {
try {
Proxy proxy = new Proxy(Proxy.Type.HTTP,
new InetSocketAddress(InetAddress.getByAddress(new byte[]{(byte)10,(byte)252,(byte)47,(byte)33}), 0));
final URL _url = new URL(url);
final URLConnection conn = _url.openConnection(proxy);
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
System.out.println(inputLine);
in.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
The code above was modelled on this answer
We're testing this with Python's SimpleHTTPServer, simply running python -m SimpleHTTPServer then trying to connect.
If we use no proxy in our Java code then the connection works correctly.
However, as soon as the VIP proxy is defined we get connection refused:
java.net.ConnectException: Connection refused
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:327)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:193)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:180)
at java.net.Socket.connect(Socket.java:546)
at java.net.Socket.connect(Socket.java:495)
at sun.net.NetworkClient.doConnect(NetworkClient.java:178)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:409)
at sun.net.www.http.HttpClient$2.run(HttpClient.java:457)
at java.security.AccessController.doPrivileged(Native Method)
at sun.net.www.http.HttpClient.privilegedOpenServer(HttpClient.java:454)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:521)
at sun.net.www.http.HttpClient.<init>(HttpClient.java:240)
at sun.net.www.http.HttpClient.New(HttpClient.java:321)
at sun.net.www.http.HttpClient.New(HttpClient.java:338)
at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:935)
at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:914)
at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:801)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1139)
at com.ocado.dsi.ConnectToUrl.attemptConnection(ConnectToUrl.java:38)
at com.ocado.dsi.ConnectToUrl.run(ConnectToUrl.java:56)
at com.ocado.dsi.ConnectToUrl.main(ConnectToUrl.java:64)
Any ideas why?
Update
When specifying the local address on a socket directly the process works fine.
I setup a Python simple socket server listening on port 8000 just as the SimpleHTTPServer used above does. Connecting to this from Java using a socket with the desired local address worked as expected: the python server recognised the incoming connection source address as that defined by the user.
Socket s = new Socket(InetAddress.getByAddress(new byte[]{(byte)10,(byte)252,(byte)47,(byte)33}), 8000, InetAddress.getByAddress(new byte[]{(byte)10,(byte)97,(byte)5,(byte)147}), 0);
s.close();
I'm going to dig into Socket#setSocketImplFactory to see whether the problem can be resolved by customising every created socket.
The problem is that both Socket#setSocketImplFactory and URL.setURLStreamHandlerFactory enable you to override the default implementation but do not give you access to the default implementation, so they seem to be very much all-or-nothing overrides. This is very annoying when you only wish tor add logic on top.

Java networking server-client error

I'm trying to program a (simple, for starters) server-client thingy, just to establish a connection and see if it works. And it does. As long as I stay inside my own four walls/network. As soon as I try to go via my routers IP the client produces a mighty fine error message. All the usual suspects have been eliminated: Router Port forwarding is on, the firewall doesn't interfere (well, it still doesn't work when I turn it off), and canyouseeme.org says that it can establish a connection to my chosen port when the server runs.
Here is the source code for the server, since I figured out it was possible to just go via the command line with a little telnetting.
When I try to establish a connection, it just says Could not open connection to the host, on port 49163:Connection failed
Server:
import java.net.*;
import java.io.*;
public class ChatServer {
public static void main(String[] args) throws IOException {
ServerSocket server = null;
try {
System.setProperty("java.net.preferIPv4Stack" , "true");
server = new ServerSocket(49163);
} catch (IOException e) {
System.err.println("Could not listen on port: 49163.");
System.exit(1);
}
Socket client = null;
try {
client = server.accept();
} catch (IOException e) {
System.err.println("Accept failed.");
System.exit(1);
}
PrintWriter out = new PrintWriter(client.getOutputStream(), true);
BufferedReader in = new BufferedReader(newInputStreamReader(client.getInputStream()));
String inputLine;
String outputLine;
out.println("Connection established");
while ((inputLine = in.readLine()) != null) {
if (inputLine.equals("exit")) {
break;
}
outputLine = inputLine;
out.println(outputLine);
}
out.close();
in.close();
client.close();
server.close();
System.out.println("Server offline");
}
}
Oh yeah, preferIP4vStack was something I picked up on Stackoverflow, but it doesn't seem to work for me.
For some reason I'm not able to inlcude the code for the client, I keep getting messages about formatting, and I just can't figure it out. But the way I see it is that I'm not even able to connect via the command line (when I try to connect to the "real" IP), so the client doesn't have to get involved. But for you who want to see the error anyway:
java.net.ConnectException: Connection refused: connect
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.PlainSocketImpl.doConnect(Unknown Source)
at java.net.PlainSocketImpl.connectToAddress(Unknown Source)
at java.net.PlainSocketImpl.connect(Unknown Source)
at java.net.SocksSocketImpl.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at java.net.Socket.<init>(Unknown Source)
at java.net.Socket.<init>(Unknown Source)
at ChatClient.main(ChatClient.java:12)
Could not open connection to the host, on port 49163:Connection failed
No it didn't. Thats not a Java message. Your code said that, when you caught a ConnectException that had a much more detailed message of its own. Print that and you might have some hope of finding what went wrong. Making up your own messages and suppressing what the exception tells you is rarely if ever a good idea.
The message will probably be one of:
'connection refused', which means you got the target host or port wrong, or there is a firewall
'connection timed out', which is a network connectivity problem
'no route to host', which is an IP routing problem
'unknown host', which again means you got the server name wrong.
I don't know if I'm suposed to laugh or cry now.
A friend told me that MAYBE, maybe the problem might be that I try to log in with the external IP from a network-intern PC, which for some mysterious reason can't get out or can't get back in.
Got someone to try and login from somewhere else, and voila! Works like a charm.

How to connect to a different computer running a Java server?

I created a simple echo server in Java. When I try it locally, it works as it should. However, when I try to connect it from a different computer using the IP address and the port number the server is running on, it never connects. Is there anything else that should be done to connect to a server from a different computer?
import java.net.Socket;
import java.net.ServerSocket;
public class EchoServer {
public static void main(String[] args) throws Exception {
// create socket
int port = 4444;
ServerSocket serverSocket = new ServerSocket(port);
System.err.println("Started server on port " + port);
// repeatedly wait for connections, and process
while (true) {
// a "blocking" call which waits until a connection is requested
Socket clientSocket = serverSocket.accept();
System.err.println("Accepted connection from client");
// open up IO streams
In in = new In (clientSocket);
Out out = new Out(clientSocket);
// waits for data and reads it in until connection dies
// readLine() blocks until the server receives a new line from client
String s;
while ((s = in.readLine()) != null) {
out.println(s);
}
// close IO streams, then socket
System.err.println("Closing connection with client");
out.close();
in.close();
clientSocket.close();
}
}
}
Please check the following things.
Is the server computer behind a network proxy ?
Does it have an independent public IP Address by which it is accessible from
anywhere ? Or, does it have an internal IP, by which it can be accessed in your LAN ?
Make sure FireWalls has an exception for port 4444. Or you may turn it of in both client and server.
If it does not help, post the exception you are getting (by editing the question). Or the server program is just freezing without any error ?
If this is on your LAN refer to the machine running your EchoServer by name (the actual machine name, I believe they show you to do it this way on the Sun Tutorial that posted this echo server excercise correct?). If that works it would help a lot in troubleshooting the issue.

Categories

Resources