Java SocketTimeoutException:读取超时
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26764252/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
SocketTimeoutException: Read time out
提问by Eriassa
It's a simple client/server based ping/pong program. Unfortunately, IT doesn't work and displays this error message:
这是一个简单的基于客户端/服务器的 ping/pong 程序。不幸的是,IT 不起作用并显示以下错误消息:
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:
它停在 CLIENT TASK 30 行,实际上客户端不会读取服务器发送的内容。这里的代码:
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;
}
}
采纳答案by dan.m was user2321368
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.
问题在于循环BufferedReader.read()
内部的使用while
与从连接的另一侧处理套接字的方式之间的交互。
..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.
..read()
只有当它正在读取的流结束时才返回 -1,在这种情况下,这实际上意味着套接字已关闭。在套接字关闭之前,服务器只是阻塞在 上read
,等待客户端发送另一个字符。由于服务器阻塞在 上read
,它永远不会发送 'pong' 回来。客户端在自己的读取上阻塞,但最终达到了超时。
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.
TCP 套接字用于处理数据流。如果你想用它来发送离散的消息,你需要在客户端和服务器之间强加一个协议,以便他们每个人都知道完整的消息何时到达。在这种情况下,客户端和服务器可以就使用终止符达成一致,以指定消息是完整的。例如,他们可以同意\n
在每条消息后发送一个作为终止符。
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);