>>分享孙卫琴的Java技术专稿和著作 书籍支持  卫琴直播  品书摘要  在线测试  资源下载  联系我们
发表一个新主题 开启一个新投票 回复文章 您是本文章第 23777 个阅读者 刷新本主题
 * 贴子主题:  【Java网络编程专题】用Java套接字访问HTTP服务器读取网页数据 回复文章 点赞(0)  收藏  
作者:sunweiqin    发表时间:2020-01-10 09:25:26     消息  查看  搜索  好友  邮件  复制  引用

本文参考笔者所写的《Java网络编程核心技术详解》,电子工业出版社出版。
点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小

在一个Socket对象中同时包含了远程服务器的IP地址和端口信息,以及客户本地的IP地址和端口信息。此外,从Socket对象中还可以获得输出流和输入流,分别用于向服务器发送数据,以及接收从服务器端发来的数据。以下方法用于获取Socket的有关信息:
  •      getInetAddress():获得远程被连接进程的IP地址。
  •        getPort():获得远程被连接进程的端口。
  •        getLocalAddress():获得本地的IP地址。
  •        getLocalPort():获得本地的端口。
  •        getInputStream():获得输入流。如果Socket还没有连接,或者已经关闭,或者已经通过shutdownInput()方法关闭输入流,那么此方法会抛出IOException。
  •        getOutputStream():获得输出流。如果Socket还没有连接,或者已经关闭,或者已经通过shutdownOutput()方法关闭输出流,那么此方法会抛出IOException。
以下例程的HTTPClient类用于访问网页www.javathinker.net/index.jsp 。该网页位于一个主机名(也叫域名)为“ www.javathinker.net ”的远程HTTP服务器上,它监听80端口。在HTTPClient类中,先创建了一个连接到该HTTP服务器的Socket对象,然后发送符合HTTP协议的请求,接着接收从HTTP服务器上发回的响应结果。


/*  HTTPClient.java */
import java.net.*;
import java.io.*;
public class HTTPClient {
  String host="www.javathinker.net";
  int port=80;
  Socket socket;
  
  public void createSocket()throws Exception{
    socket=new Socket(host,80);
  }
  
  public void communicate()throws Exception{
    StringBuffer sb=new StringBuffer("GET "
                 +"/index.jsp"+" HTTP/1.1\r\n");
    sb.append("Host: "+host+"\r\n");
    sb.append("Accept: */*\r\n");
    sb.append("Accept-Language: zh-cn\r\n");
    sb.append("Accept-Encoding: gzip, deflate\r\n");
    sb.append("User-Agent:HTTPClient\r\n");
    sb.append("Connection: Keep-Alive\r\n\r\n");

    //发出HTTP请求
    OutputStream socketOut=socket.getOutputStream();
    socketOut.write(sb.toString().getBytes());  
    socketOut.flush();
      
    //接收响应结果
    InputStream socketIn=socket.getInputStream();
    ByteArrayOutputStream buffer=new ByteArrayOutputStream();
    byte[] buff=new byte[1024];  
    int len=-1;
    while((len=socketIn.read(buff))!=-1){
      buffer.write(buff,0,len);
    }
    //把字节数组转换为字符串
    System.out.println(new String(buffer.toByteArray()));  
    socket.close();
  }
  
  public static void main(String args[])throws Exception{
    HTTPClient client=new HTTPClient();
    client.createSocket();
    client.communicate();
  }
}
以上HTTPClient类在发送数据时,先把字符串形式的请求信息转换为字节数组(即字符串的编码),然后再发送:
socketOut.write(sb.toString().getBytes());
HTTPClient类在接收数据时,把接收到的字节写到一个ByteArrayOutputStream中,它具有一个容量能够自动增长的缓冲区。如果socketIn.read(buff)方法返回-1,则表示读到了输入流的末尾:
ByteArrayOutputStream buffer=new ByteArrayOutputStream();
byte[] buff=new byte[1024];
int len=-1;
while((len=socketIn.read(buff))!=-1){
   buffer.write(buff,0,len);
}

//把字节数组转换为字符串
System.out.println(new String(buffer.toByteArray()));  

运行HTTPClient程序时,会打印服务器端发送的HTTP响应结果:

HTTP/1.1 200 OK
Date: Mon, 23 Sep 2019 09:11:35 GMT
Server: Apache
Set-Cookie: JSESSIONID=
     2C81276B53C7D7D9487A9B59CB3D7EBC; Path=/; HttpOnly
Content-Type: text/html;charset=GBK
Vary: Accept-Encoding
Content-Encoding: gzip
Access-Control-Allow-Origin: *
Content-Length: 587
Keep-Alive: timeout=5, max=50
Connection: Keep-Alive

¬昑蛶?0網趙橎X? 笘 褨]╔?HUO菼L皃烊v?猳蛾 T瓯廟┣鷊?
……

HTTP响应结果包括响应头和响应正文,中间以空行隔开。以上响应正文部分是乱码。这是因为www.javathinker.net服务器在发送正文内容时,先把它压缩成为GZIP格式,客户端需要对压缩数据进行解压,才能得到正文内容。而本范例未对压缩的正文数据解压,就直接将它打印出来,所以会显示乱码。

更专业的抓取网页数据的各种技巧,请参考另一篇文章:盘点用Java抓取HTTP服务器和FTP服务器的网页数据或图片等数据的实用技巧

作者:孙卫琴



程序猿的技术大观园:www.javathinker.net



[这个贴子最后由 admin 在 2021-10-09 10:54:06 重新编辑]
网站系统异常


系统异常信息
Request URL: http://www.javathinker.net/WEB-INF/lybbs/jsp/topic.jsp?postID=1389

java.lang.NullPointerException

如果你不知道错误发生的原因,请把上面完整的信息提交给本站管理人员