How to restart ServerSocket after IOException?
My server socket sometimes gets an EOFException and then stops accepting new connections. To solve this I have tried closing the old server socket and creating a new one after the exception is thrown. However even after the new server socket is created, new connections are not accepted. Can some one see why this does not work?
public Server() throws IOException {
try {
listen(port);
}
catch (IOException e) {
System.out.println("Server() - IO exception");
System.out.println(e);
/*when an exception is caught I close the server socket and try opening it a new one */
serverSocket.close();
listen(port);
}
}
private void listen(int port) throws IOException {
serverIsListening = true;
serverSocket = new ServerSocket(port);
System.out.println("<Listening> Port: " + serverSocket);
while (serverIsListening) {
if (eofExceptionThrown){ //manually triggering an exception to troubleshoot
serverIsListening = false;
throw new EOFException();
}
//accept the next incoming connection
Socket socket = serverSocket.accept();
System.out.println("[New Conn] " + socket);
ObjectOutputStream oOut = new ObjectOutputStream(socket.getOutputStream());
// Save the streams
socketToOutputStreams.put(socket, oOut);
// Create a new thread for this connection, and put it in the hash table
socketToServerThread.put(socket, new ServerThread(this, socket));
}
}
2x entry point , one form catch: never ends well.
try {
listen(port);
}
catch (IOException e) {
System.out.println("Server() - IO exception");
System.out.println(e);
/*when an exception is caught I close the server socket and try opening it a new one */
serverSocket.close();
listen(port);
}
I would do in a loop, while a boolean is true:
while(needToListen){
try{
listen(port)
}catch(Exception ex){
if(exception is what needed to break the loop, like a message has a string on it){
break;
}
}
}
if(needToListen){
Log.e("something unexpected, unrecoverable....");
}
My server socket sometimes gets an EOFException and then stops accepting new connections
No it doesn't. ServerSockets never get EOFExceptions. Rather, one of your accepted Sockets is getting an EOFException, which is only to be expected, and you are closing both that Socket, which is correct, and the ServerSocket, which is incorrect. Exceptions on accepted sockets don't affect the listening socket.
Related
I have a server and a client set up in this way. I can't find the cause of the EOFException, because it happens randomly. It throws the following exception every time a client connects, but I can't figure out the source of it. It always occurs before it reads what the client has sent. The exception always is at this line:
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
Here is the exception:
java.io.EOFException
at java.base/java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2860)
at java.base/java.io.ObjectInputStream$BlockDataInputStream.readShort(ObjectInputStream.java:3355)
at java.base/java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:939)
at java.base/java.io.ObjectInputStream.<init>(ObjectInputStream.java:381)
at com.denesgarda.Socketeer.data.End$3.run(End.java:62)
at com.denesgarda.Socketeer.data.End$3.run(End.java:76)
at com.denesgarda.Socketeer.data.End$3.run(End.java:76)
at com.denesgarda.Socketeer.data.End.listen(End.java:83)
at Server.<init>(Server.java:10)
at SStart.main(SStart.java:5)
Here is my server code:
if(listener == null) this.voidListener();
ServerSocket serverSocket = new ServerSocket(port);
End THIS = this;
TimerTask timerTask = new TimerTask() {
#Override
public void run() {
try {
Socket socket = serverSocket.accept();
socket.setSoTimeout(10000);
Connection connection = new Connection(THIS, new End((((InetSocketAddress) socket.getRemoteSocketAddress()).getAddress()).toString().replace("/","")), port, listener);
try {
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
Object o = objectInputStream.readObject();
if (o.equals("01101100 01101001 01110011 01110100 01100101 01101110 00100000 01110011 01110100 01100001 01110010 01110100")) {
listener.event(new ConnectionEvent(connection));
listener.event(new ConnectionSuccessfulEvent(connection));
}
else {
listener.event(new ReceivedEvent(connection, o));
}
socket.close();
}
catch(EOFException e) {
e.printStackTrace();
}
this.run();
}
catch(Exception e) {
e.printStackTrace();
}
}
};
timerTask.run();
Here is my client code:
if(listener == null) this.voidListener();
Socket socket = new Socket(address, port);
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
send("Message");
public void send(Object object) throws IOException {
Socket socket = new Socket(THAT.getAddress(), this.port);
OutputStream outputStream = socket.getOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(object);
socket.close();
}
What I've Tried
I've tried to fix this issue many times before. I tried to create object output streams. I've switched the order that I initialize the object input stream and object output stream. This is so that the server doesn't get frozen in a deadlock with the client. I have no idea what could be causing this error.
I think I know what is going on here, but I can't be certain because your code is fragmentary, and the symptoms are not well characterized. (The exceptions are unlikely to really be random, for example.)
First there is one indisputable fact. A one side of a connection sees an EOFException because the other side has closed the network connection. That's what that exception means.
In your case, the server gets the exception in the ObjectInputStream constructor because the constructor attempts to read an object stream header that the client side never sends ... on that connection.
Now, the theory. I think I know why. Here is the relevant part of your code (with some bits snipped out for brevity).
Socket socket = new Socket(address, port);
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
[...]
socket.close();
[...]
}
});
send("Message");
public void send(Object object) throws IOException {
Socket socket = new Socket(THAT.getAddress(), this.port);
[...]
}
Notice that there are two sockets! The first one is created and passed to the shutdown hook. The second one is created and used within send and then closed.
I think the problem is the first Socket. When that is created, it establishes a connection to the server. The server code will accept it and then attempt to read. The read will block ... since the client side hasn't written anything to that socket. The client will then call send which opens and uses a different Socket.
Eventually, the client application exits.
When it exits, the shutdown hook closes the first socket. That causes the server side to see the end of stream ... and triggers the EOFException.
So how to fix this?
It rather depends on the "big picture". Is the real client sending a single message to the server, or does it need to reuse the socket to send multiple messages?
Assuming the former, the solution is simple:
Get rid of the code that creates a socket and passes it to a shutdown hook. As you have written it, it serves no useful purpose.
Rewrite the send method to use try with resources; e.g.
public void send(Object object) throws IOException {
try (Socket socket = new Socket(THAT.getAddress(), this.port);
OutputStream os = socket.getOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(os)) {
oos.writeObject(object);
}
}
Note that the above will automatically close the 3 resources in the correct order.
I'm developing an application that can control mouse from android phone. The problem is communication is very slow with socket mouse lags while moving. I want to move mouse pointer as the user moves his finger on screen. How can I optimize this code?
On computer side I'm using this code
try {
serverSocket = new ServerSocket(4444);
} catch (IOException e) {
System.out.println("Could not listen on port: 4444");
}
System.out.println("Server started. Listening to the port 4444");
while (true) {
try {
clientSocket = serverSocket.accept();
inputStreamReader = new InputStreamReader(
clientSocket.getInputStream());
bufferedReader = new BufferedReader(inputStreamReader);
message = bufferedReader.readLine();
System.out.println(message);
Robot robot = new Robot();
switch (message) {
case "first":
ix = MouseInfo.getPointerInfo().getLocation().x;
iy = MouseInfo.getPointerInfo().getLocation().y;
break;
case "lclickp":
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
break;
case "lclickr":
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
break;
//several more cases
} catch (IOException | AWTException ex) {
System.out.println("Problem in message reading");
}
and I'm using this on android side.
private class SendMessage extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
try {
client = new Socket(Login.IP, 4444); // connect to the server
printwriter = new PrintWriter(client.getOutputStream(), true);
printwriter.write(messsage); // write the message to output stream
printwriter.flush();
printwriter.close();
client.close(); // closing the connection
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
Don't create a new connection per message: keep the socket open. At the server end, process multiple messages per accepted socket, until readLine() returns null.
Now I just beginning learning and I'm not good in socket programming but I think the server should wait for new connections in a separate thread because the ServerSocket.accept() method blocks until there is a connection and causes my app frozen at that line.
Thread conWaitingThread = new Thread(new Runnable(){
while (true){
//try
socket = serverSocket.accept();
//catch
}
void startWaiting(){
comWaitingThread.start();
}
void endWaiting(){
if(conWaitingThread.isAlive()){
conWaitingThread.interrupt();
}
}
and for reading msg from client,
while(input.readLine()!=null){
try{
message = input.readLine();
//ur switch case
}catch (ioException e){
//do catch
}
}
For client side, create socket and iostreams once and let them open. Not close the iostreams as closing iostreams closes the respective socket too. May open socket and io in onCreate and close in onDestroy. Be aware that input.readLine() on serverSide waits the new line char and printWriter.write() does not automatically add that. So you may not get any incoming data although printWriter.flush() is called and you need to concat "\n" on writing.
On the PC Side of things:
Consider refactoring into a few helper classes, perhaps, one for Connect, one for sending updates, and one for Disconnect. Then, you will only need to connect and disconnect once per session.
It's good practice to set a tick rate on both the server and client to prevent over-using CPU time and other resources. There is no need to update mouse coordinates more frequently than the refresh rate of typical monitor can update (60fps / 16.6ms) for example.
I'm creating a simple http server. I have a master thread that waits in a loop for a connection to be accepted. Once a connection is accepted, I create a new worker thread to handle the connection, passing the accepted socket as an argument. Once a connection is accepted, a new thread is created for it, however the master thread will loop again, create another socket with the same connection and create another duplicated thread.
Master thread waiting for connections.
public void run(){
while(Tester.serverStatus != "quit"){
try {
Socket clientSocket = serverSocket.accept();
new Thread(new Worker(clientSocket)).start();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
this.stop();
} catch (IOException e) {
e.printStackTrace();
}
return;
}
public void stop() throws IOException{
serverSocket.close();
return;
}
Worker thread pseudocode
public void run(){
InputStream input = clientSocket.getInputStream();
//read from stream, validate request and setup the response in a byte array
input.close();
DataOutputStream output = new DataOutputStream(clientSocket.getOutputStream());
output.write(responseByteArray);
output.flush();
output.close();
clientSocket.close();
return;
}
Any ideas as to why the accept() method isn't being blocked after the first connection is accepted? It just keeps on creating duplicate Worker threads with the same Socket.
Thanks
What you describe is not possible.
You undoubtedly have some static variables somewhere that should be instance members of Worker, such as the input and/or output streams, and/or the socket itself.
I am working on a Java client/server application that involves P2P communication over TCP. I'm trying to implement TCP Hole Punching as described here: http://www.brynosaurus.com/pub/net/p2pnat/#sec-tcp. This requires simultaneously listening on and attempting to establish an outgoing connection using the same local TCP port. Apparently, this should work if the SO_REUSEADDR socket option is used, which I am setting via the setReuseAddress() method in Java. However, this is not working as I expected. Here is some test code:
import java.io.IOException;
import java.net.*;
public class Test {
public static void main(String args[]) {
new Thread() {
public void run() {
try {
ServerSocket ss = new ServerSocket();
ss.setReuseAddress(true);
ss.bind(new InetSocketAddress(7077));
ss.accept();
} catch (Exception e) {
System.out.println("ServerSocket exception: " + e.getMessage());
}
}
}.start();
Socket s;
while (true) {
s = new Socket();
try {
s.setReuseAddress(true);
s.bind(new InetSocketAddress(7077));
s.connect(new InetSocketAddress("192.168.0.103", 7077));
break;
} catch (Exception e) {
System.out.println("Socket exception: " + e.getMessage());
try { s.close(); } catch (IOException e1) { }
try { Thread.sleep(1000); } catch (InterruptedException e1) { }
}
}
}
}
This works as expected in Windows 7: the ServerSocket listens on port 7077 in its own thread and the Socket repeatedly attempts to connect to 192.168.0.103:7077. However, under Linux (Ubuntu) only the first Socket connection attempt works, and subsequent attempts get the "Address already in use" BindException. Shouldn't I be able to establish an outgoing connection from a TCP source port that I'm also listening on simultaneously, and to reuse the local port number immediately after closing the socket, since I have the SO_REUSEADDR option enabled?
In Linux, both sockets need to set SO_REUSEADDR socket option. Thus, if we want two sockets, sock1 and sock2 to be bound ot the same port, then s2 would be able to reuse the port/address only if both sock1 and sock2 set SO_REUSEADDR.
You are never closing your client socket, unless there is an exception, making the point of SO_REUSEADDR a no-op.
....
s = new Socket();
try {
// ...
} catch (Exception e) {
System.out.println("Socket exception: " + e.getMessage());
// remove try block from here
try { Thread.sleep(1000); } catch (InterruptedException e1) { }
} finally {
try { s.close(); } catch (IOException e1) { }
}
....
In the above, I moved the closing of the socket to a newly created finally block so it is always executed, even if you break out the global while loop.
Since the socket is now closed under all conditions, the SO_REUSEADDR will use correctly now.
I am making a prototype client & server so that I can understand how to handle reconnects.
The server ought to create a serversocket and listen forever. A client may connect, send its data, and close its socket but it will not send a "I'm done and closing" type message to the server. For this reason, the server gets a EOFException when it does a readByte() since the remote client has closed. In the error handler for the EOFException, it will close the socket and open a new one.
Here's the problem: The client sometimes gets a SocketWriteError when it does the outputStream.write() call even after it successfully opens the socket/inputstream/outpustream. It may have something to do with the frequency that I'm opening and closing these sockets. One interesting thing is that the client does an arbitrary number of writes/close/reconnects before crapping out. It will sometimes crap out on the first reconnect, other times it will take 50 reconnects before seeing the SocketWriteError.
Here's the error on the client side:
java.net.SocketException: Connection reset by peer: socket write error
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)
at java.net.SocketOutputStream.write(SocketOutputStream.java:115)
at bytebuffertest.Client.main(Client.java:37)
Here are some snippets of code:
SERVER:
public static void main(String[] args)
{
Server x = new Server();
x.initialize();
}
private void initialize()
{
ServerSocket s;
InputStream is;
DataInputStream dis;
while (true) //ADDED THIS!!!!!!!!!!!!!!!!!!!!!!
{
try
{
s = new ServerSocket(4448);
s.setSoTimeout(0);
s.setReuseAddress(true);
is = s.accept().getInputStream();
System.out.println("accepted client");
dis = new DataInputStream(is);
try
{
byte input = dis.readByte();
System.out.println("read: " + input);
} catch (Exception ex)
{
System.out.println("Exception");
dis.close();
is.close();
s.close();
}
} catch (IOException ex)
{
System.out.println("ioexception");
}
}
}
CLIENT:
public static void main(String[] args)
{
Socket s;
OutputStream os;
try
{
s = new Socket("localhost", 4448);
s.setKeepAlive(true);
s.setReuseAddress(true);
os = s.getOutputStream();
int counter = 0;
while (true)
{
try
{
os.write((byte) counter++);
os.flush();
os.close();
s.close();
s = new Socket("localhost", 4448);
s.setKeepAlive(true);
s.setReuseAddress(true);
os = s.getOutputStream();
} catch (Exception e)
{
e.printStackTrace();
System.err.println("ERROR: reconnecting...");
}
}
} catch (Exception ex)
{
ex.printStackTrace();
System.err.println("ERROR: could not connect");
}
}
Does anyone know how to properly reconnect?
Don't close the ServerSocket on an error, just .accept() a new connection.
What I normally do is each time ServerSocket.accept() returns a Socket, I spawn off a thread to handle sending and receiving from that Socket. That way you're ready to start accepting a new connection as soon as somebody wants to connect to you.