server端`
package com.example.demo.socket;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class Server {
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket(8080);
serverSocket.setSoTimeout(10000);//连接阻塞时间,即等待client连接的时间,也就是accept()超时时间
Socket socket = serverSocket.accept();//accept()这里阻塞10S,如果这段时间内没client连接上来则报错“accept time out”
System.out.println(socket);
socket.setSoTimeout(5000);//读取client 的输入流读取超时时间,即while循环内的input.readline()
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintStream out = new PrintStream(socket.getOutputStream());
while (true) {
Thread.sleep(3000);
String fromclient = input.readLine();//这里阻塞5S,1.在这段时间没读到client的信息即报错“Read timed out”;2.阻塞时如果client断开,报错“Connection reset”;3.如果client socket如果调用close,这里直接读到null,不会报错
System.out.println("from client:" + fromclient);
String now = LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME);
out.println(now);
//socket.close();
}
}
}
client端
package com.example.demo.socket;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class Client {
public static void main(String[] args) throws Exception {
Socket socket = new Socket("localhost", 8080);
socket.setSoTimeout(15000);//同服务端,读取超时时间
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintStream out = new PrintStream(socket.getOutputStream());
while (true) {
String now = LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME);
out.println(now);
String fromserver = input.readLine();//这里阻塞5S,1.在这段时间没读到client的信息即报错“Read timed out”;2.阻塞时如果client断开,报错“Connection reset”;3.如果server socket如果调用close,这里与server不同,报错“Software caused connection abort: recv failed”
System.out.println("from server:" + fromserver);
Thread.sleep(2000);
//socket.close();
}
}
}
结论
- 服务端aceept()阻塞:即等待client端来连接,有client来连接立即解除阻塞,超时无连接报错“accept time out”
- 服务端/客户端input.readline()阻塞:连接建立后,读取client/server socket的输入流的消息,这里至少可能有三种情形:
1.在阻塞这段时间没读到client/server的信息即报错“Read timed out”;
2.阻塞时如果client/server任何一方断开(杀进程),另一方报错“Connection reset”;
3.如果client socket如果调用close,服务端读取流直接读到null;如果server socket如果调用close,客户端报错“Software caused connection abort: recv failed” - 阻塞超时时间都通过setSoTimeout设置