客户端-服务器套接字程序没有像预期的那样遇到死锁
Client-server socket program not experiencing deadlock as expected
我有一个示例套接字程序。客户端只发送数字,服务器回显它们。
客户:
public class Client {
private Socket socket;
private BufferedReader in;
private PrintWriter out;
public Client(String hostname, int port) throws IOException {
socket = new Socket(hostname, port);
//Create a BufferedReader with buffer size of 1
in = new BufferedReader(new InputStreamReader(socket.getInputStream()), 1);
out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
}
public void sendRequest(String x) throws IOException {
out.print(x + "\n");
out.flush();
}
public void close() throws IOException {
in.close();
out.close();
socket.close();
}
public String getReply() throws IOException {
String reply = in.readLine();
return reply;
}
public static void main(String[] args) {
try {
Client client = new Client("localhost", 4949);
for (int i = 0; i < 100000; i++){
System.err.println("Sending: "+i);
client.sendRequest(String.valueOf(i));
}
for (int i = 0; i < 100000; i++){
client.getReply();
}
client.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
服务器:
public class Server {
private ServerSocket serverSocket;
public Server(int port) throws IOException {
serverSocket = new ServerSocket(port);
}
private void handle(Socket socket) throws IOException {
System.err.println("client connected");
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// Create a PrintWriter with buffer size 1
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()), 1));
try {
for (String line = in.readLine(); line != null; line = in.readLine()) {
out.print(line + "\n");
out.flush();
}
} finally {
out.close();
in.close();
}
}
public void serve() throws IOException {
while (true) {
// block until a client connects
Socket socket = serverSocket.accept();
try {
handle(socket);
} catch (IOException ioe) {
ioe.printStackTrace(); // but don't terminate serve()
} finally {
socket.close();
}
}
}
public static void main(String[] args) {
try {
Server server = new Server(4949);
server.serve();
} catch (IOException e) {
e.printStackTrace();
}
}
}
这似乎是一个显而易见的问题,但为什么客户端的输入缓冲区没有填满并导致死锁?客户端在阅读任何回复之前发送 10000 个数字。这不会导致客户端的接收缓冲区被填满,也导致服务器的发送缓冲区被填满吗?我什至将 BufferedReader 和 BufferedWriter 的缓冲区大小设为 possible.However,当我 运行 这段代码时,没有死锁。
因为您忽略了发送方的套接字发送缓冲区和接收方的套接字接收缓冲区的存在。这些在内核中,它们之间可以清楚地容纳所有服务器的输出。
我有一个示例套接字程序。客户端只发送数字,服务器回显它们。
客户:
public class Client {
private Socket socket;
private BufferedReader in;
private PrintWriter out;
public Client(String hostname, int port) throws IOException {
socket = new Socket(hostname, port);
//Create a BufferedReader with buffer size of 1
in = new BufferedReader(new InputStreamReader(socket.getInputStream()), 1);
out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
}
public void sendRequest(String x) throws IOException {
out.print(x + "\n");
out.flush();
}
public void close() throws IOException {
in.close();
out.close();
socket.close();
}
public String getReply() throws IOException {
String reply = in.readLine();
return reply;
}
public static void main(String[] args) {
try {
Client client = new Client("localhost", 4949);
for (int i = 0; i < 100000; i++){
System.err.println("Sending: "+i);
client.sendRequest(String.valueOf(i));
}
for (int i = 0; i < 100000; i++){
client.getReply();
}
client.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
服务器:
public class Server {
private ServerSocket serverSocket;
public Server(int port) throws IOException {
serverSocket = new ServerSocket(port);
}
private void handle(Socket socket) throws IOException {
System.err.println("client connected");
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// Create a PrintWriter with buffer size 1
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()), 1));
try {
for (String line = in.readLine(); line != null; line = in.readLine()) {
out.print(line + "\n");
out.flush();
}
} finally {
out.close();
in.close();
}
}
public void serve() throws IOException {
while (true) {
// block until a client connects
Socket socket = serverSocket.accept();
try {
handle(socket);
} catch (IOException ioe) {
ioe.printStackTrace(); // but don't terminate serve()
} finally {
socket.close();
}
}
}
public static void main(String[] args) {
try {
Server server = new Server(4949);
server.serve();
} catch (IOException e) {
e.printStackTrace();
}
}
}
这似乎是一个显而易见的问题,但为什么客户端的输入缓冲区没有填满并导致死锁?客户端在阅读任何回复之前发送 10000 个数字。这不会导致客户端的接收缓冲区被填满,也导致服务器的发送缓冲区被填满吗?我什至将 BufferedReader 和 BufferedWriter 的缓冲区大小设为 possible.However,当我 运行 这段代码时,没有死锁。
因为您忽略了发送方的套接字发送缓冲区和接收方的套接字接收缓冲区的存在。这些在内核中,它们之间可以清楚地容纳所有服务器的输出。