简单 Server/Client 套接字:阻塞 - Java
Simple Server/Client Socket: BLOCKING - Java
我有一个客户端和一个服务器,这是一个经典示例,它试图以非常简单的方式模拟 http 协议。首先客户端发送数据,而服务器打印数据,然后相反。在以下代码中,由于未知原因,服务器或客户端阻塞。
客户端向服务器发送数据,服务器接收数据并打印。但它只是在打印数据后阻塞。如果我关闭客户端的输出流 (out.close()),客户端应该获取服务器的数据,但会抛出 IOException 并显示消息:套接字已关闭。
我的问题是为什么会阻塞?我必须用 EOS 触发输出吗?
客户
import java.nio.*;
import java.nio.channels.*;
import java.net.*;
import java.util.*;
import java.io.IOException;
import java.io.*;
public class block_client_webclient
{
public static void main(String [] args)
{
try{
Socket s = new Socket("localhost", 8080);
OutputStreamWriter out = new OutputStreamWriter(s.getOutputStream());
InputStreamReader in = new InputStreamReader(s.getInputStream());
//WRITE
out.write("GET / HTTP/1.1\r\nUser-agent: Agent 2.0 Browser\r\nAccept: */*\r\nAccept-Language: en-US,en;q=0.5\r\nConnection: keep-alive\r\n\r\n");
out.flush();
out.close();
if (s.isConnected()==true && s.isClosed()==false) System.out.println("OPEN");
else System.out.println("CLOSED");
char[] bin = new char[400];
int r=0;
//READ
while((r=in.read(bin))!=-1) { System.out.println("Input data: "+r+" bytes"); System.out.print(bin); bin= new char[400]; };
System.out.println(r);
s.close();
}
catch (IOException ex) {System.out.println(ex.getMessage());}
}
}
服务器
import java.nio.*;
import java.nio.channels.*;
import java.net.*;
import java.util.*;
import java.io.IOException;
import java.io.*;
public class block_server_webserver
{
public static void main(String [] args)
{
while(true)
{
try{
ServerSocket server = new ServerSocket(8080);
Socket connection = server.accept();
try{
OutputStreamWriter out = new OutputStreamWriter( connection.getOutputStream());
InputStreamReader in = new InputStreamReader( connection.getInputStream());
char[] bin = new char[400];
int r=0;
int readsofar=0;
//READ
while((r=in.read(bin))!=-1) { System.out.print(bin); bin= new char[400]; };
System.out.println("END");
//WRITE
out.write("Server: BlockServer 1.0\r\nHost: 192.168.1.1\r\n\r\n");
out.flush();
System.out.println("Just written data to "+connection.getRemoteSocketAddress());
connection.close();
} catch (IOException ex) { connection.close();}
}catch (IOException ex) {}
}
}
}
服务器不应等待套接字关闭(因为一旦发生这种情况,它将无法回写)。
与其读取直到 returns -1(关闭),它应该读取到请求的末尾(在 http headers 的情况下为两行),并开始发送输出为一旦发生这种情况,然后可能会关闭连接以通知客户端没有更多数据(在 http 中,连接通常会保持打开状态一段时间,客户端知道在收到足够的字节后停止读取 Content-length header).
执行 out.close() 会导致套接字关闭异常,因为当您关闭 input/output 流时,与其相关的套接字也会关闭。这意味着在您的客户端程序中,您将无法在关闭套接字后读入。
首先,取出 out.close() 而不是检查 -1,尝试创建一个 "exit" 字符串。如果服务器读取了退出字符串,识别出它需要停止在 while 循环中并中断; (可以用一个简单的 if 语句来完成)。另外,通常我会使用缓冲的 reader、String x 和 readLine() 而不是 char 数组 + read().
while (true) {
in.read(bin);
if (bin[0] == '^') { // or something like that
break;
}
System.out.print(bin);
bin = new char[400];
}
只有当您完全使用完套接字后,close() 才会流。
我有一个客户端和一个服务器,这是一个经典示例,它试图以非常简单的方式模拟 http 协议。首先客户端发送数据,而服务器打印数据,然后相反。在以下代码中,由于未知原因,服务器或客户端阻塞。 客户端向服务器发送数据,服务器接收数据并打印。但它只是在打印数据后阻塞。如果我关闭客户端的输出流 (out.close()),客户端应该获取服务器的数据,但会抛出 IOException 并显示消息:套接字已关闭。
我的问题是为什么会阻塞?我必须用 EOS 触发输出吗?
客户
import java.nio.*;
import java.nio.channels.*;
import java.net.*;
import java.util.*;
import java.io.IOException;
import java.io.*;
public class block_client_webclient
{
public static void main(String [] args)
{
try{
Socket s = new Socket("localhost", 8080);
OutputStreamWriter out = new OutputStreamWriter(s.getOutputStream());
InputStreamReader in = new InputStreamReader(s.getInputStream());
//WRITE
out.write("GET / HTTP/1.1\r\nUser-agent: Agent 2.0 Browser\r\nAccept: */*\r\nAccept-Language: en-US,en;q=0.5\r\nConnection: keep-alive\r\n\r\n");
out.flush();
out.close();
if (s.isConnected()==true && s.isClosed()==false) System.out.println("OPEN");
else System.out.println("CLOSED");
char[] bin = new char[400];
int r=0;
//READ
while((r=in.read(bin))!=-1) { System.out.println("Input data: "+r+" bytes"); System.out.print(bin); bin= new char[400]; };
System.out.println(r);
s.close();
}
catch (IOException ex) {System.out.println(ex.getMessage());}
}
}
服务器
import java.nio.*;
import java.nio.channels.*;
import java.net.*;
import java.util.*;
import java.io.IOException;
import java.io.*;
public class block_server_webserver
{
public static void main(String [] args)
{
while(true)
{
try{
ServerSocket server = new ServerSocket(8080);
Socket connection = server.accept();
try{
OutputStreamWriter out = new OutputStreamWriter( connection.getOutputStream());
InputStreamReader in = new InputStreamReader( connection.getInputStream());
char[] bin = new char[400];
int r=0;
int readsofar=0;
//READ
while((r=in.read(bin))!=-1) { System.out.print(bin); bin= new char[400]; };
System.out.println("END");
//WRITE
out.write("Server: BlockServer 1.0\r\nHost: 192.168.1.1\r\n\r\n");
out.flush();
System.out.println("Just written data to "+connection.getRemoteSocketAddress());
connection.close();
} catch (IOException ex) { connection.close();}
}catch (IOException ex) {}
}
}
}
服务器不应等待套接字关闭(因为一旦发生这种情况,它将无法回写)。
与其读取直到 returns -1(关闭),它应该读取到请求的末尾(在 http headers 的情况下为两行),并开始发送输出为一旦发生这种情况,然后可能会关闭连接以通知客户端没有更多数据(在 http 中,连接通常会保持打开状态一段时间,客户端知道在收到足够的字节后停止读取 Content-length header).
执行 out.close() 会导致套接字关闭异常,因为当您关闭 input/output 流时,与其相关的套接字也会关闭。这意味着在您的客户端程序中,您将无法在关闭套接字后读入。
首先,取出 out.close() 而不是检查 -1,尝试创建一个 "exit" 字符串。如果服务器读取了退出字符串,识别出它需要停止在 while 循环中并中断; (可以用一个简单的 if 语句来完成)。另外,通常我会使用缓冲的 reader、String x 和 readLine() 而不是 char 数组 + read().
while (true) {
in.read(bin);
if (bin[0] == '^') { // or something like that
break;
}
System.out.print(bin);
bin = new char[400];
}
只有当您完全使用完套接字后,close() 才会流。