用IO,NIO,MINA三种方式抓百度,返回结果大不同
采用阻塞IO,NIO,MINA三种方式去抓取百度首页,打印出首页的内容。我发现NIO和MINA返回的结果跟阻塞IO返回的结果不同,尤其是MINA,差别很大。JDK版本为1.6.0_29
首先是阻塞方式的IO去连接:
Socket socket = new Socket("www.baidu.com", 80);OutputStream os = socket.getOutputStream();
os.write("GET / HTTP/1.1rn".getBytes());
os.write("Host:www.baidu.comrnrn".getBytes());
os.flush();
InputStream is = socket.getInputStream();
String line = null;
BufferedReader br = new BufferedReader(new InputStreamReader(is));
while((line=br.readLine()) != null) {
System.out.println(line);
}
之后将返回的结果保存为一个html文件,a.html
第二次,使用NIO的方式抓取百度
InetSocketAddress socketAddress = new InetSocketAddress(
"www.baidu.com", 80);
channel = SocketChannel.open(socketAddress);
//channel.configureBlocking(false); 使用阻塞或者非阻塞的方式返回结果都一样
byte[] buf = "GET / HTTP/1.1rnHost:www.baidu.comrnrn".getBytes();
ByteBuffer bb = ByteBuffer.allocate(buf.length);
bb.put(buf);
bb.flip();
channel.write(bb);
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (channel.read(buffer) != -1) {
buffer.flip();
if(buffer.limit() > 0) {
System.out.println(new String(buffer.array()));
}
buffer.clear();
}
将返回结果保存为b.html
最后是用MINA:
NioSocketConnector connector = new NioSocketConnector();
DefaultIoFilterChainBuilder chain = connector.getFilterChain();
chain.addLast("myChin", new ProtocolCodecFilter(
new TextLineCodecFactory()));
connector.setHandler(new ClientHandle());
connector.setConnectTimeout(30);
ConnectFuture cf = connector.connect(new InetSocketAddress("www.baidu.com",80));
cf.awaitUninterruptibly();
cf.getSession().getCloseFuture().awaitUninterruptibly();
connector.dispose();
ClientHandle类:
public class ClientHandle extends IoHandlerAdapter {
@Override
public void messageReceived(IoSession session, Object message)
throws Exception {
System.out.println(message);
}
@Override
public void messageSent(IoSession session, Object message) throws Exception {
System.out.println(message);
}
@Override
public void sessionOpened(IoSession session) throws Exception {
session.write("GET / HTTP/1.0rn");
// session.write("GET / HTTP/1.1rn");
// session.write("Host:www.baidu.comrnrn");
}
}
用MINA采用HTTP1.0和HTTP1.1的方式返回结果都是一样的。
将mina返回的结果保存为c.html
最后将这三个html都打开,对比正常的www.baidu.com页面,发现阻塞IO获取到的结果是正确的,和原始的baidu首页是一模一样,而NIO获取到的有一点点不同,主要是在格式上有一点不同。但是MINA差别就非常大了。从对比来看,阻塞IO返回的内容应该是完全正确的,NIO好像少了一点内容。
这里我弄不清楚的是,为什么NIO和阻塞IO获取的结果会不同,将NIO设置为阻塞的方式返回的结果还是跟阻塞IO有差别。而MINA则很离谱了,返回的结果跟原始的百度页面差很多,似乎是一些数据没获取到,不知道为什么。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
NIO 收到那多余的部分其实是上一次的在bytebuffer中的缓存,
是什么问题呢、楼主解决了吗?@超级呆子
Mina获得数据可能只是一部分,得继续读取后面还有
使用mina时候看看编码转换问题是否有影响
网页是别人的,不好控制,调试起来不方便
或者你自己起个jsp界面然后用3中方式获取看看,
又试了一下NIO的方式,代码如下:
InetSocketAddress ia = new InetSocketAddress("www.baidu.com",80);
SocketChannel socket = SocketChannel.open(ia);
String header = "GET / HTTP/1.1rnHost:www.baidu.comrnrn";
byte[] buf = header.getBytes();
ByteBuffer bb = ByteBuffer.allocate(buf.length);
bb.put(buf);
bb.flip();
socket.write(bb);
ByteBuffer buffer = ByteBuffer.allocate(1024);
while(socket.read(buffer) != -1) {
buffer.flip();
//if(buffer.limit() > 0) {
System.out.print(new String(buffer.array()));
//}
buffer.clear();
}
这回返回的内容,保存为html后打开,显示的结果跟正常的百度就非常类似了,但是却多收到了一些内容:
如果是阻塞IO,到红框那段后面就没有了,但是NIO收到的结果却多出了一些内容。
我不知道哪里有问题,请指教。
应该是你代码的问题