I was trying to implement a simple HTTP client using java NIO. But I get an error that the connection was forcibly closed by the remote host before the all data was read. Using ordinary sockets, everything works fine.
Here's an example:
private static final String REQUEST = "GET / HTTP/1.1\r\nHost: stackoverflow.com\r\n\r\n";
void channel() {
try {
SocketChannel sc = SocketChannel.open(new InetSocketAddress("stackoverflow.com", 80));
while (!sc.isConnected()) {
}
ByteBuffer buf = ByteBuffer.allocate(16*1024);
buf.put(REQUEST.getBytes());
buf.rewind();
sc.write(buf);
buf.rewind();
while (sc.read(buf) > 0) {
buf.rewind();
System.out.println(new String(buf.array()));
buf.clear();
}
} catch (IOException e) {
e.printStackTrace();
}
}
void socket() {
try {
Socket s = new Socket("stackoverflow.com", 80);
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
out.write(REQUEST);
out.flush();
String l;
while ((l = in.readLine()) != null) {
System.out.println(l);
}
开发者_运维技巧 } catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// Works:
new Test().socket();
// Exception:
new Test().channel();
}
This is the exception I get:
java.io.IOException: An existing connection was forcibly closed by the remote host
at sun.nio.ch.SocketDispatcher.read0(Native Method)
at sun.nio.ch.SocketDispatcher.read(Unknown Source)
at sun.nio.ch.IOUtil.readIntoNativeBuffer(Unknown Source)
at sun.nio.ch.IOUtil.read(Unknown Source)
at sun.nio.ch.SocketChannelImpl.read(Unknown Source)
at at.maph.tlsproxy.client.Test.channel(Test.java:39)
at at.maph.tlsproxy.client.Test.main(Test.java:70)
Has it something to do that I'm using a buffered reader with the socket, but not with the channel? If so, how can I make a channel buffer the read data?
Ok, I figured it out now after checking write()
's return value, which was 16.384, so random data was sent to the server. The problem was with calling rewind
on the buffer, instead, flip
has to be used:
void channel() {
try {
SocketChannel sc = SocketChannel.open(new InetSocketAddress("stackoverflow.com", 80));
ByteBuffer buf = ByteBuffer.allocate(16*1024);
buf.put(REQUEST.getBytes());
buf.flip(); // <--------- Here
sc.write(buf);
buf.rewind();
while (sc.read(buf) > 0) {
buf.flip(); // <------- And here
System.out.println(new String(buf.array()));
buf.clear();
}
} catch (IOException e) {
e.printStackTrace();
}
}
精彩评论