SocketTimeoutException:读取超时 [英] SocketTimeoutException: Read time out

查看:8005
本文介绍了SocketTimeoutException:读取超时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个简单的基于客户端/服务器的ping / pong程序。
不幸的是,IT不起作用并显示以下错误消息:

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)

它停在在CLIENT TASK 30系列中,客户端实际上没有读取服务器发送的内容。
这里代码:

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

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

}


推荐答案

问题在于在中使用 BufferedReader.read()循环之间的交互,以及从连接另一端处理套接字的方式。

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()只会当它正在读取的流已经结束时返回-1,在这种情况下,这实际上意味着套接字已关闭。在套接字关闭之前,服务器只是阻塞读取,等待客户端发送另一个字符。由于服务器在读取时阻塞,它将永远不会发送'pong'。客户端阻止自己的读取,但最终达到了超时。

..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套接字用于处理数据流。如果要使用它来发送离散消息,则需要在客户端和服务器之间强制执行协议,以便每个人都知道完整消息何时到达。在这种情况下,客户端和服务器可以就使用终结符来约定,以指定消息是完整的。例如,他们可以同意在每封邮件后发送一个 \ n 作为终结符。

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

这篇关于SocketTimeoutException:读取超时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆