Java套接字模拟http请求的问题



当我使用java bio套接字模拟http get请求时,我需要调用socket.shutdownOutput((;socket.getInputStream((.read((读取正确的数据,否则它将继续阻塞。当我使用SocketChannel模拟http请求时,不会发生这种情况。下面是我写的测试程序。

public static void socket1(String host,int port,String path) throws Exception{
Socket socket = new Socket();
socket.connect(new InetSocketAddress(host,port));
OutputStream out = socket.getOutputStream();
InputStream in = socket.getInputStream();
{
out.write(("GET " + path + " HTTP/1.1rn").getBytes());
out.write(("Host: " + host + ":" + port + "rn").getBytes());
out.write("rn".getBytes());
out.flush();
}
//This method needs to be called so that the following can correctly read the data returned by the server.
// Otherwise, it will always be blocked in the in.read() method
//socket.shutdownOutput();

ByteArrayOutputStream bos = new ByteArrayOutputStream();
int len;
while ((len = in.read()) != -1) {
bos.write(len);
System.out.println(len);
}
System.out.println("[" + new String(bos.toByteArray()) + "]");
bos.close();
in.close();
out.close();
socket.close();
}

当socket.shutdownOutput((未被调用时,该程序将始终在in.read((上被阻止。当socket.sshutdownOutput((被调用时。in.read((将返回-1。

如果我使用SocketChannel模拟,上述情况不会发生,并且可以获得正确的数据。以下是的代码示例

public static void socket2(String host,int port,String path) throws Exception{
Selector selector = Selector.open();
SocketChannel channel = SocketChannel.open();
channel.configureBlocking(false);
channel.register(selector, SelectionKey.OP_CONNECT);
channel.connect(new InetSocketAddress(host,port));
while (true) {
selector.select();
Set<SelectionKey> selectedKeys = selector.selectedKeys();
for (Iterator<SelectionKey> it = selectedKeys.iterator(); it.hasNext();) {
SelectionKey key = it.next();
it.remove();
if (key.isConnectable()) {
SocketChannel client = ( SocketChannel)key.channel();
if (client.isConnectionPending()) { 
client.finishConnect(); 
client.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));
{
client.write(ByteBuffer.wrap(("GET " + path + " HTTP/1.1rn").getBytes()));
client.write(ByteBuffer.wrap(("Host: " + host + ":" + port + "rn").getBytes()));
client.write(ByteBuffer.wrap("rn".getBytes()));
}
}
} else if (key.isReadable()) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
SocketChannel client = (SocketChannel) key.channel();
ByteBuffer buf = (ByteBuffer) key.attachment();
buf.clear();
int length = client.read(buf);
buf.flip();
while(buf.hasRemaining()) {
bos.write(buf.get());
}
System.out.println(buf);
//System.out.println(Arrays.toString(bos.toByteArray()));
System.out.println("["+new String(bos.toByteArray())+"]");
bos.close();
Thread.sleep(1000 * 2);
client.write(ByteBuffer.wrap(("GET " + path + " HTTP/1.1rn").getBytes()));
client.write(ByteBuffer.wrap(("Host: " + host + ":" + port + "rn").getBytes()));
client.write(ByteBuffer.wrap("rn".getBytes()));
}
}
}
  1. InputStream.read在流结束时返回-1

  2. 要结束套接字OutputStream,您需要调用shutdown

很简单,流在结束之前不会结束。现在没有更多的数据与正在结束的流不同;您总是可以写更多的数据,直到流结束。

最新更新