SocketTimeoutException: Read time out

放肆的年华 提交于 2020-01-11 05:40:12

问题


It's a simple client/server based ping/pong program. Unfortunately, IT doesn't work and displays this error message:

java.net.SocketTimeoutException: Read timed out
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.read(Unknown Source)
    at java.net.SocketInputStream.read(Unknown Source)
    at sun.nio.cs.StreamDecoder.readBytes(Unknown Source)
    at sun.nio.cs.StreamDecoder.implRead(Unknown Source)
    at sun.nio.cs.StreamDecoder.read(Unknown Source)
    at java.io.InputStreamReader.read(Unknown Source)

It stops at the CLIENT TASK 30 line, in practise the client doesn't read what the server has sent. Here the code:

SERVER

package serverClient;

import java.net.*;
import java.io.*;
import java.util.concurrent.*;

public class Server {

    public static void main(String[]args){


        ExecutorService esp= Executors.newFixedThreadPool(50);
        try(ServerSocket ss= new ServerSocket(1027)){
            while(true){
                try{

                    Socket s=ss.accept();
                    Callable<Void> task=new ServerTask(s);
                    esp.submit(task);

                }
                catch(BindException be){}
                catch(ConnectException ce){}
                catch(NoRouteToHostException nrthe){}
                catch(IOException ioe){ioe.printStackTrace();}
            }
        }
        catch(Exception e){e.printStackTrace();}

    }
}

SERVER TASK

package serverClient;

import java.util.concurrent.*;
import java.net.*;
import java.io.*;

public class ServerTask implements Callable <Void> {

    Socket s;

    ServerTask(Socket s){
        this.s=s;
    }

    public Void call(){
        BufferedWriter writer=null;
        BufferedReader reader=null;

        try{

            reader=new BufferedReader(new InputStreamReader(s.getInputStream()));
            writer=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));

            int i=0;
            StringBuilder sb=new StringBuilder();
            while((i=reader.read())!=-1){
                sb.append((char)i);
            }
            System.out.println("The client sends: "+sb);


            writer.write("pong");
            writer.flush();

        }   
        catch(IOException ioe){ioe.printStackTrace();}
        finally{

                try {
                    writer.close();
                } 
                catch (IOException ioe) {ioe.printStackTrace();}

            if(reader!=null){
                try{
                    reader.close();
                }
                catch(IOException ioe){ioe.printStackTrace();}
            }
            try{
                s.close();
            }
            catch(IOException ioe){ioe.printStackTrace();}

        }
        return null;
    }
}

CLIENT

package serverClient;

import java.io.IOException;
import java.net.*;
import java.util.concurrent.*;

public class Client {

    public static void main(String[] args) {

        ExecutorService es= Executors.newSingleThreadExecutor();

        try {

            Socket s= new Socket(InetAddress.getLocalHost(),1027);
            try {
                s.setSoTimeout(50000);
            } 
            catch(SocketException se){se.printStackTrace();}

            Callable<Void> task=new ClientTask(s);
            es.submit(task);

        } 
        catch (UnknownHostException uhe) {uhe.printStackTrace();} 
        catch (IOException ioe) {ioe.printStackTrace();}

    }

}

CLIENT TASK

package serverClient;

import java.util.concurrent.*;
import java.net.*;
import java.io.*;

public class ClientTask implements Callable <Void>{

    Socket s;

    ClientTask(Socket s){
        this.s=s;
    }

    public Void call(){

        BufferedWriter writer=null;
        BufferedReader reader=null;

        try{

            writer=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
            reader=new BufferedReader(new InputStreamReader(s.getInputStream()));

            writer.write("ping");
            writer.flush();

            int i=0;
            StringBuilder sb=new StringBuilder();
            while((i=reader.read())!=-1){
                System.out.println("I'm reading.");
                sb.append((char)i);
            }
            System.out.println("The server sends: "+sb);


        }
        catch(IOException ioe){ ioe.printStackTrace();}

        finally{

                try {
                    writer.close();
                } 
                catch (IOException ioe) {ioe.printStackTrace();}

            if(reader!=null){
                try{
                    reader.close();
                }
                catch(IOException ioe){ioe.printStackTrace();}
            }
            try{
                s.close();
            }
            catch(IOException ioe){ioe.printStackTrace();}

        }
        return null;
    }

}

回答1:


The problem is with the interaction between your use of BufferedReader.read() inside a while loop, and with the way you handle the socket from the other side of the connection.

..read() will only return -1 when the stream it is reading from has ended, which in this case will essentially mean that the socket is closed. Until the socket is closed, the server is just blocking on read, waiting for the client to send another character. As the server is blocking on read, it will never get to send 'pong' back. The client is blocking on its own read, but eventually your timeout is reached.

TCP sockets are for dealing with streams of data. If you want to use it to send discrete messages, you'll need to impose a protocol between the client and the server so that they each know when a complete message has arrived. In this case, the client and server can agree upon using a terminator character, to specify that a message is complete. For instance, they could agree to send a \n as a terminator after each message.

So, for example, in your client, the relevant code would look like:

writer.write("ping");
writer.write('\n');
writer.flush();

int i=0;
StringBuilder sb=new StringBuilder();
while((i=reader.read())!=-1){
    char c = (char)i;
    if(c == '\n')
        break;
    sb.append(c);
}
System.out.println("The server sends: "+sb);


来源:https://stackoverflow.com/questions/26764252/sockettimeoutexception-read-time-out

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!