|
本文参考笔者所写的《Java网络编程核心技术详解》,电子工业出版社出版。
在一个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 重新编辑]
|
|