If another application on the PC is connected to the same remote IP address, a java application will fail to connect properly.
This can also happen when a exits abruptly without closing the socket channel. The connection can be blocked and it is impossible to connect during a subsequent session.
What can I do to ensure that no matter the state of the connection in the underlying OS, my program will connect 100% of the time ?
I am looking for a cross platform solution (Windows & Ubuntu)
public void connect() throws CommunicationIOException {
try {
if (isConnected()) {
return;
}
socket = SocketChannel.open();
socket.socket().connect(new InetSocketAddress(getHostname(), getPort()), getConnectionTimeout());
if (!isConnected()) {
throw new CommunicationIOException("Failed to establish the connection");
}
socket.configureBlocking(false);
} catch (final IOException ex) {
throw new CommunicationIOException(
"An error occurred while connecting to " + getHostname() + " on port " + getPort(), ex);
}
}
.
public boolean isConnected() {
if (socket == null) {
return false;
} else {
return socket.isConnected();
}
}
.
public void close() throws CommunicationIOException {
if (socket != null) {
try {
socket.close();
} catch (final IOException ex) {
throw new CommunicationIOException(
MessageFormat.format(
"An error occurred while attempting to close the connection to {}:{}",
getHostname(), getPort()), ex);
}
}
}
If another application on the PC is connected to the same remote IP address, a java application will fail to connect properly.
No it won't, unless the server is improperly programmed.
This can also happen when a exits abruptly without closing the socket channel.
No it can't, again unless something is improperly programmed.
The connection can be blocked
No it can't.
and it is impossible to connect during a subsequent session.
No it isn't.
What can I do to ensure that no matter the state of the connection in the underlying OS, my program will connect 100% of the time ?
Nothing in this life will give you a 100% guarantee. However your fears as expressed above are baseless.
Related
The problem is that I have defined some broker uri which could be inactive.
Then createConnection from ActiveMQConnectionFactory doesn't throw any exception. I need to handle such situation and if createConnection doesn't work because of uri won't be available then I should mark my service as unhealthy.
boolean healthy = true;
Connection conn = null;
try {
final ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("failover:(tcp://localhost:8080)?jms.prefetchPolicy.all=0&initialReconnectDelay=1000&maxReconnectDelay=30000&maxReconnectAttempts=20");
conn = factory.createConnection(this.userName, this.password);
} catch (JMSException e) {
healthy = false;
} finally {
if (conn != null) {
try {
conn.close();
} catch (JMSException e) {
healthy = false;
}
}
}
So you want create connection to fail with an exception but you are also using the failover transport? Doesn't that seem at odds to you?
The failover transport usage is resulting in the create to succeed because the failover transport is doing exactly what you asked it to do which is to try and establish a connection repeatedly until the configured number of attempts is made. Calling a method like create session will block and eventually throw an error once the failover transport gives up. Alternately you could set an exception listener that will be signalled once the connection is closed because the failover transport runs out of reconnect attempts.
According to this post [When does OnWebSocketClose fire in Jetty 9, OnClose fire for me correctly.
but i can not reconnect, because I have not correct situation. (websocett is closed and I can not send any message)
where and when I can reconnect in websocket problem (close by network problem or timeout or kickout by sever after n seconds without handshaking)
I'm not sure if you have solved this issue but I managed to come up with a solution to reconnect a WebSocket connection.
For my scenario, I would like to reconnect my WebSocket connection if #OnWebSocketError method is triggered. Initially I implemented it like this
Implementation A:
#OnWebSocketError
public void onError(Throwable e) {
someMethodToReconnect();
}
and inside someMethodToReconnect
if (client == null) {
client = new WebSocketClient(sslContextFactory);
client.setMaxIdleTimeout(0);
}
if (socket == null) {
socket = new ReaderSocket(); // ReaderSocket is the name of my #WebSocket class
}
try {
client.start();
client.connect(socket, new URI(socketUrl), request);
} catch (Exception e) {
LOGGER.error("Unable to connect to WebSocket: ", e);
}
However, this led to another issue. There are 2 types of error thrown back to me if the server is not up. The exceptions are java.net.ConnectException and org.eclipse.jetty.websocket.api.UpgradeException.
The flow would be:
Initial request to WebSocket server (server is not up)
java.net.ConnectException thrown
org.eclipse.jetty.websocket.api.UpgradeException thrown
And in Implementation A, someMethodToReconnect would be called twice.
This led to Implementation B
#OnWebSocketError
public void onError(Throwable e) {
if (e instanceof ConnectException) {
// Attempt to reconnect
someMethodToReconnect();
} else {
// Ignore upgrade exception
}
}
So far Implementation B works fine, however I'm trying to find out if there's any other exceptions that would be thrown.
This question already has answers here:
How can I fix 'android.os.NetworkOnMainThreadException'?
(66 answers)
Closed 7 years ago.
What I was trying to do:
I was trying to build a test app, for now, simply establishing connection between the app on Android phone (4.2.2)(as client) and a java application running on pc (windows 8)(as server) via sockets connection.
What I've done already:
I've made the programs for both client and server in java on pc and tested them positively (Connection got established).
The network:
Both my phone and pc are connected to wifi at my home.ipconfig on pc shows address 192.168.56.1 while on logging into router it shows address of my pc to be 192.168.0.108 (Probably I don't understand networking :P).
The code:
client(Android)
public void connectPC(View view)
{
try
{
clientSocket = new Socket("192.168.0.108",1025);
outstream = clientSocket.getOutputStream();
instream = clientSocket.getInputStream();
data_out = new DataOutputStream(outstream);
data_in = new DataInputStream(instream);
statusView.setText("Connected!");
}
catch (Exception e)
{
statusView.setText("Error: "+e.getMessage());
}
}
The Server:
import java.net.*;
import java.io.*;
public class ServerSide extends Thread
{
ServerSocket serverSocket;
public ServerSide(int port) throws IOException
{
serverSocket = new ServerSocket(1025);
serverSocket.setSoTimeout(10000);
}
public void run()
{
while(true)
{
System.out.println("Waiting for client on port : "+ serverSocket.getLocalPort());
Socket server;
try {
server = serverSocket.accept();
System.out.println("Connected to : " +server.getRemoteSocketAddress());
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println(e.getMessage());
}
}
}
public static void main(String... args)
{
int port=6066;
try
{
Thread t = new ServerSide(port);
t.start();
}
catch(IOException e)
{
System.out.println(e.getMessage());
}
}
}
The Problem:- The connection simply doesn't establish, the catch block shows e.getMessage() as null.
PS I've tried 192.168.56.1 ip address too. And added uses permission in manifest file
Any help in this regard please..!
You need to print the stacktrace rather than just the exception message. That will give you more information to debug the problem ... including the name of the exception, and the place where it was thrown.
Also, it is a bad idea to catch Exception and attempt to recover from it. Catching Exception could catch all sorts of exceptions that you were never expecting. Recovering from exceptions that you weren't expecting is risky ... because you cannot be sure it is a safe thing to do. It is typically better to let the application die ...
I would like to give you some suggestions:
use asynctask in android for networking activities otherwise NetworkOnMainThreadException occur because it is good to run all time consuming activities in background.Also keep in mind do all task in doBackgroung function of asynctask and then update and publish result with help of onPostExecute() and onProgress().
If you are not using asynctask then simply use thread and perform all networking activity on separate thread.
In java software ,track IP address by using Enumeration instead of InetAddress because Enumeration will show all IP address on network and probably you will find answer of your question.(Try to connect to all the IP that is shown by Enumeration method and connection is established with suitable one automatically)
I wrote a client which basically just open a socket and send content over the connection. ( the content follows the Http protocol)
The problem I'm facing regards to the question - how and when should i close the connection.
The issue is that the connection sometime closes too early ("FIN" is sent to the server before the server answered).
in this case the server's answer is lost.
I tried to use Thread.sleep before closing the connection but nothing seems to affect the time between the content is sent and the "FIN" message is sent. (viewed in Wireshark)
The answer sometimes arrive and sometimes not ( race condition).
How can i delay the "FIN" message so i won't miss the server's response?
i added the relevant class. The relevant function is sendContentOverSocket
public class SocketClient {
private String hostName;
private int portNumber;
private Socket ConnectionSocket;
public void init(String hostName, int portNumber){
this.hostName = hostName;
this.portNumber = portNumber;
this.ConnectionSocket=createSocketConnection();
}
private Socket createSocketConnection() {
Socket socket = null;
try {
socket = new Socket(this.hostName, this.portNumber);
return socket;
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return socket;
}
public void sendContentOverSocket(String content) {
try {
PrintWriter out = new PrintWriter(
ConnectionSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(
ConnectionSocket.getInputStream()));
out.print(content);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
out.close();
in.close();
ConnectionSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
TCP works with a concept called a half close.
When you close the socket that is an indication that you are not going to send anymore.
In your explanation I see "FIN is sent to the server before the server answered", if you are the client, that would mean that you have performed a close on the socket.
If you expect a result from a server within a certain time frame you need some kind of timing mechanism, possibly making use of select in combination with a timeout.
If the server closes his end of the connection, you detect this by receiving bytes in receive. Usually this means that you have to close the socket too.
So in conclusion there is 3 reasons for you to close the socket :
the server closes his end of the socket basically saying i am not going to send anymore
you have waited for a while and you are tired of waiting and decide to close the socket yourself.
any other error conditions but usually they all appear like receiving 0 bytes or a negative number.
You should close the connection after you've read the response, of course. Difficult to see the mystery here. No sleeps. If you don't read the response (a) you can't know whether the request succeeded or failed, and (b) the server is liable into encounter an exception as well.
Your code is poor quality. All those methods should propagate exceptions instead of catching them internally and returning null.
In case of Java 7, since all three classes, i.e. Socket, PrintWriter, BufferedReader, implement AutoCloseable and based on the fact, that you want to close socket right after you invoke sendContentOverSocket(String content) try to use the following code:
public class SocketClient {
private String hostName;
private int portNumber;
public void init(String hostName, int portNumber) {
this.hostName = hostName;
this.portNumber = portNumber;
}
public void sendContentOverSocket(String content) {
try (Socket socket = new Socket(this.hostName, this.portNumber);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
out.print(content);
} catch(IOException e) {
//Appropriate exception handler
}
}
}
In this case Java will close all resources properly by itself.
If you use Java 6 or earlier try to use try-finally block instead:
solved.
i now understand how it works.
what i was missing in the client is the attempt to read from the input Stream.
When you try to read
while ((inputFromServer = in.readLine()) != null)
the client waits for input. The only thing that will break this loop is the server closing the connection.
after that happens you can safely close the connection on the client side. No need to delay the FIN and such...
I'm creating a Java based server.
I'm using a server socket to accept incoming messages.
However at some point within my program I want the server socket to listen to another port.
I close the server socket. And start a new one with my new port. Everything is fine.
However when I change the server socket to the previous port again, it gives me an error.
I've read things that the server socket stays a while in a timed-out state after I closed it.
So here is my question:
Can I circumvent this timed-out state of the server socket and make my port available again after I closed it and want to listen to the same port again?
EDIT: my function to make and listen to a server socket & my function to invalidate a server socket and create a new one right after
public void makeServerSocketWithPort(int portnr) throws IOException, Exception
{
server = new ServerSocket(portnr);
server.setReuseAddress(true);
while(!portchanged)
{
Socket sock = server.accept();
System.out.println(server.getLocalPort());
System.out.println(sock.getLocalPort());
handler = new Requesthandler(sock); //should be in a thread
System.out.println(server.getLocalPort());
System.out.println(sock.getLocalPort());
}
}
public void invalidateRequestHandler(int newPort)
{
if(server != null)
{
portchanged = true;
try {
server.close();
} catch (IOException ex) {
Logger.getLogger(Controlserver.class.getName()).log(Level.SEVERE, null, ex);
}
}
portchanged = false;
makeServerSocketWithPort(newPort);
}
Error StackTrace:
Exception in thread "main" java.net.SocketException: Socket closed
at java.net.PlainSocketImpl.socketAccept(Native Method)
at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:408)
at java.net.ServerSocket.implAccept(ServerSocket.java:462)
at java.net.ServerSocket.accept(ServerSocket.java:430)
at stuff.Controlserver.makeServerSocketWithPort(Controlserver.java:63)
at stuff.Main.main(Main.java:44)
EDIT:
a second try to fix it to no avail:
public void makeServerSocketWithPort(int portnr, boolean invalidated) throws IOException, Exception
{
if(!invalidated)
{
server = new ServerSocket();
server.setReuseAddress(true);
server.bind(new InetSocketAddress(portnr));
portchanged = false;
}
else
{
//TODO: invalidate the old requestHandler
if(server != null)
{
try
{
server.close();
server = null;
}
catch (IOException ex)
{
Logger.getLogger(Controlserver.class.getName()).log(Level.SEVERE, null, ex);
}
}
if(server.isClosed())
{
System.out.println("closed biatch!");
}
else
{
System.out.println("surprise moddafakkaaaaa!!!");
}
//---------------------------------------------
//then make new requestHandler with new port
portchanged = true;
}
while(!portchanged)
{
if(server != null && !server.isClosed() && !invalidated)
{
Socket sock = server.accept();
System.out.println(server.getLocalPort());
System.out.println(sock.getLocalPort());
System.out.println("test");
handler = new Requesthandler(sock); //should be in a thread
handler.start();
System.out.println("ja harm");
System.out.println(server.getLocalPort());
System.out.println(sock.getLocalPort());
}
else
{
portchanged = true;
}
}
if(portchanged)
{
portchanged = false;
makeServerSocketWithPort(portnr, false);
}
}
Again this works fine normally. I can navigate through my html pages. When I change my port number via one of the webpages it is properly stored and changed in my storage xml files.
But when I changed my socket and navigate immediately to a page through that socket, it says it is closed and is not working until i restart my application.
I'm still looking for a way to circumvent this restart.
Well I solved the mystery.
Thing was I just needed to reconstruct my classes a bit to support the threading a bit better. Instead of closing the socket and then making a new thread I started a new thread and then closed the socket. After a bit of fiddling it appeared to work just fine.
This is the normal Server socket behavior by OS. The OS keeps the port open in WAIT_TIMEOUT state. To get around this, try using ServerSocket.setReuseAddress(boolean on). This will enable/disable the SO_REUSEADDR socket option. Check here for Documentation.
Quoting the javadoc of method setReuseAddress
When a TCP connection is closed the connection may remain in a timeout
state for a period of time after the connection is closed (typically
known as the TIME_WAIT state or 2MSL wait state). For applications
using a well known socket address or port it may not be possible to
bind a socket to the required SocketAddress if there is a connection
in the timeout state involving the socket address or port.
Enabling SO_REUSEADDR prior to binding the socket using
bind(SocketAddress) allows the socket to be bound even though a
previous connection is in a timeout state.
Use TCPview to see all the opened ports in your system. You can close those ports which are in use.