网络编程
网络编程的基础知识
网络协议与TCP/IP 计算机之间的连接协议规则
IP地址和Port(端口号) 本地回路的IP地址:127.0.0.1
端口号的范围为0~65535之间,0~1024之间的端口数是用于一些知名的网络服务和应用。
UDP与TCP
TCP,传输控制协议是面向连接的通信协议
UDP,用于数据协议,是无连接通信协议
TCP、UDP的数据帧格式简单图例:(其中协议类型用区UDP与TCP)
协议类型 源IP 目录IP 源端口 目录端口 帧序号 帧数据
Socket
Socket 是网络驱动层提供给应用程序编程的接口和一种机制
可以把Socket比喻成一个港头码头,应用程序只要把货物放到港口码头,就算完成
货物的运送,应用程序只需等待货物到达码头
java中的网络编程类
位于java.net包中
DatagramSocket类用于UDP通信
ServerSocket类用于TCP通信的服务器端
Socket类 此类实现客户端套接字,套接字是两台机器间通信的端点
UDP网络程序
DatagrmeSocket类
构造函数:
DatagramSocket() 构造数据报套接字并将其绑定到本地主机上任何可用的端口。
DatagramSocket(int port) 创建数据报套接字并将其绑定到本地主机上的指定端口。
DatagramSocket(int port, InetAddress laddr) 创建数据报套接字,将其绑定到指定的本地地址。
close() 关闭此数据报套接字
send(DatagramPacket p) 从此套接字发送数据报包。
receive(DatagramPacket p) 从此套接字接收数据报包。
DatagramPacket类
如果把DatagramSocket比作创建的港口码头,那么DatagramPacket就是发送和接收数据的集装箱
构造函数:
DatagramPacket(byte[] buf, int length) 构造 DatagramPacket,用来接收长度为 length 的数据包
DatagramPacket(byte[] buf, int length, InetAddress address, int port) 构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号
方法:getPort() 返回某台远程主机的端口号、getAddress()返回某台机器的 IP 地址
getData()返回数据缓冲区、getLength() 返回将要发送或接收到的数据的长度
例1:
例2:
UDP网络聊天程序
(只有UDP才能发送广播地址)
TCP 网络程序
TCP 网络程序的工作原理
TCP客户端程序与TCP报务器端程序的交互过程:
(1)服务器程序创建一个ServerSocket,然后调用accept方法等待客户来连接.
(2)客户端程序创建一个Socket并请求与服务器建立连接。
(3)服务器接收客户的连接请求,并创建一个新的Socket与该客户建立专线连接
(4)建立了连接的两个Socket在一个单独的线程(由服务器程序创建)上对话.
(5)服务器开始等待新的连接请求,当新的连接请求到达时,重复步骤(2)到步骤(5)的过程。
ServerSocket
ServerSocket() 创建非绑定服务器套接字。
ServerSocket(int port) 创建绑定到特定端口的服务器套接字。
ServerSocket(int port, int backlog) 利用指定的 backlog 创建服务器套接字并将其绑定到指定的本地端口号。
ServerSocket(int port, int backlog, InetAddress bindAddr) 使用指定的端口、侦听 backlog 和要绑定到的本地 IP 地址创建服务器。
close() 关闭此套接字。
accept() 侦听并接受到此套接字的连接。
Socket
Socket() 通过系统默认类型的 SocketImpl 创建未连接套接字
Socket(InetAddress address, int port) 创建一个流套接字并将其连接到指定 IP 地址的指定端口号。
Socket(InetAddress address, int port, InetAddress localAddr, int localPort) 创建一个套接字并将其连接到指定远程地址上的指定远程端口。
Socket(String host, int port) 创建一个流套接字并将其连接到指定主机上的指定端口号。
Socket(String host, int port, InetAddress localAddr, int localPort) 创建一个套接字并将其连接到指定远程主机上的指定远程端口。
getInputStream() 返回此套接字的输入流。
getOutputStream() 返回此套接字的输出流。
简单的TCP服务程序
1。TCP服务程序必须先启动运行,TCP客户机程序才能连接上TCP报务器程序。
2。使用Windows提供的telnet程序测试TCP服务器程序。
3。使用BufferedReader包装类,从网络输入流中一次读取一行文本。
4。如何打开telnet程序的本地回显功能。
windows DOS窗口输入telnet 地址 端口 (测试)
实例1
实例2 TCP网络聊天程序
实例3 (服务与多个客户端会话)
如何检测和解决端口冲突问题
1、使用netstat命令查看当前正在被使用的TCP端口号。(netstat -na)
2、通过一个配制参数来指定TCP服务程序所使用的端口。
3、将用户指定的端口号保存到一个文件中,当服务器程序下次启动运行时,直接从文件中读取那个端口号。
TCP客户端程序
在TCP网络连接上传递对象
1、ObjectInputStream和ObjectOutputStream可以从底层输入流中读取对象类型的数据和将对象数据写入到底层输出流。
2、ObjectInputstream和ObjectOutputstream来包装底层网络字节流,TCP服务器和TCP客户端之间就可以传递对象类型的数据。
3、编程实例:(通过网络传输Java对象)
访问Internet网络资源
java.net包中还有URL、URLDecoder、URLEncoder、URLConnection、HttpURLConnection等类。
URL(Uniform Resure Locator统一资源定位符)
1、URL的基本组成:协议、主机名、端口号、资源名。
2、URL编码规则:
将空格转换为加号(+)。
对0~9,a~z,A~Z之间的字符保持不变。
对于所其它的字符,有这个字符的当前字符集编码在内存中的十六进制
格式表示,并在每个字节前加上一个百分号(%)。如字符“+”用%2B表示
,字符“=”用%3D表示,字符“&”用%26表示,每个中文字符在内存中占两个
字节,字符“中”用%D6%D0表示,字符“国”用%B9%FA表示。
3、java.net包中提供了URLEncoder和URLecoder这两个类,来实现URL编码和解码。
HTTP协议
TTTP协议的会话过程
基于HTTP 1.0协议的客户机与服务器的信息交换过程(客户机--建立连接--发送请求信息——》服务器--发出响应信息--关闭连接--》客户机);
基于HTTP 1.1协议的客户机与服务器的信息交换过程(客户机--建立连接--发出第1~n次连接-》服务器--发出第1~n次连接--关闭连接--》客户机);
HTTP请求消息 一个完整的请求消息包括:一个请求行、若干消息头、以及实体内容。
一个完整的响应消息包括:一个状态行、若干消息头、以及体内容。
几个HTTP消息头
1、Connection 用于指定处理完本次请求/响应后,客户端与服务器是否继续保持连接,设置值可以为keep-Alive和close.
2、Accept-Language 用于指定客户机期望服务器返回的文档所使用的语言,可以指定多个以逗号分隔的国家语言。
3、Content-Length 用于表示实体内容的长度(字节数)。
4、Range 用于指定服务器只需返回文档中的部分内容及内容范围,有以下几种使用格式:
Range:bytes=100-599
Range:bytes=100-
Range:bytes=-100
5、Content-Range 用于指定服务器返回的部分实体内容的位置信息,例如:Content-Range:bytes 2543-4531/7898
telnet www.g.cn 80
GET / HTTP/1.1
Hosst:
Accept-Language: zh-cn
URL类
构造函数(都可能引发MalformedURLException异常):
URL(String spec) 根据 String 表示形式创建 URL 对象。
URL(String protocol, String host, int port, String file) 根据指定 protocol、host、port 号和 file 创建 URL 对象。
URL(String protocol, String host, int port, String file, URLStreamHandler handler) 根据指定的 protocol、host、port 号、file 和 handler 创建 URL 对象。
URL(String protocol, String host, String file) 根据指定的 protocol 名称、host 名称和 file 名称创建 URL。
URL(URL context, String spec) 通过在指定的上下文中对给定的 spec 进行解析创建 URL。
URL(URL context, String spec, URLStreamHandler handler) 通过在指定的上下文中用指定的处理程序对给定的 spec 进行解析来创建 URL。
工厂设计模式
URL类的setURLStreamHandlerFactory(URLStreamHandlerFactory fac)设置应用程序的 URLStreamHandlerFactory。在一个给定的 Java 虚拟机中,此方法最多只能调用一次。
URLStreamHandlerFactory类的createURLStreamHandler(String protocol) 创建具有指定协议的新 URLStreamHandler 实例。
URLConnetion和HttpURLConnetin类
通过在 URL 上调用 openConnection 方法创建连接对象。
处理设置参数和一般请求属性。
使用 connect 方法建立到远程对象的实际连接。
远程对象变为可用。远程对象的头字段和内容变为可访问。
setRequestProperty(String key, String value) 设置一般请求属性。
getHeaderFields() 返回头字段的不可修改的 Map。
getInputStream() 和 getOutputStream() 返回从此打开的连接读取的输入出流
getHeaderField(int n) 返回第 n 个头字段的值。
getHeaderField(String name) 返回指定的头字段的值。
getContentLength() 返回 content-length 头字段的值。
getContentEncoding() 返回 content-encoding 头字段的值。
getContentType() 返回 content-type 头字段的值。
一个HTTP连接可以被多个HttpUPLConnection实例对象共享,调用HttpURLConnection的disconnect方法可以关闭底层共享网络。
实例:
网络编程的基础知识
网络协议与TCP/IP 计算机之间的连接协议规则
IP地址和Port(端口号) 本地回路的IP地址:127.0.0.1
端口号的范围为0~65535之间,0~1024之间的端口数是用于一些知名的网络服务和应用。
UDP与TCP
TCP,传输控制协议是面向连接的通信协议
UDP,用于数据协议,是无连接通信协议
TCP、UDP的数据帧格式简单图例:(其中协议类型用区UDP与TCP)
协议类型 源IP 目录IP 源端口 目录端口 帧序号 帧数据
Socket
Socket 是网络驱动层提供给应用程序编程的接口和一种机制
可以把Socket比喻成一个港头码头,应用程序只要把货物放到港口码头,就算完成
货物的运送,应用程序只需等待货物到达码头
java中的网络编程类
位于java.net包中
DatagramSocket类用于UDP通信
ServerSocket类用于TCP通信的服务器端
Socket类 此类实现客户端套接字,套接字是两台机器间通信的端点
UDP网络程序
DatagrmeSocket类
构造函数:
DatagramSocket() 构造数据报套接字并将其绑定到本地主机上任何可用的端口。
DatagramSocket(int port) 创建数据报套接字并将其绑定到本地主机上的指定端口。
DatagramSocket(int port, InetAddress laddr) 创建数据报套接字,将其绑定到指定的本地地址。
close() 关闭此数据报套接字
send(DatagramPacket p) 从此套接字发送数据报包。
receive(DatagramPacket p) 从此套接字接收数据报包。
DatagramPacket类
如果把DatagramSocket比作创建的港口码头,那么DatagramPacket就是发送和接收数据的集装箱
构造函数:
DatagramPacket(byte[] buf, int length) 构造 DatagramPacket,用来接收长度为 length 的数据包
DatagramPacket(byte[] buf, int length, InetAddress address, int port) 构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号
方法:getPort() 返回某台远程主机的端口号、getAddress()返回某台机器的 IP 地址
getData()返回数据缓冲区、getLength() 返回将要发送或接收到的数据的长度
例1:
package udpSocket;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
public class UDPSend {
public static void main(String args[]){
DatagramSocket ds = null;
try {
ds = new DatagramSocket();
String msg = "Hello good Luck!";
ds.send(new DatagramPacket(msg.getBytes(), msg.length(), InetAddress.getByName("127.0.0.1"), 8888));
ds.close();
} catch (SocketException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
package udpSocket;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class UDPRecv {
public static void main(String args[]){
DatagramSocket ds =null;
try {
ds=new DatagramSocket(8888);
byte buf[] =new byte[1024];
DatagramPacket dp = new DatagramPacket(buf,1024);
System.out.println("发送说:"+new String(buf,0,dp.getLength())+
"IP:"+dp.getAddress().getHostAddress()+"端口:"+dp.getPort());
ds.close();
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
例2:
UDP网络聊天程序
package udpchat;
import java.awt.BorderLayout;
import java.awt.Frame;
import java.awt.List;
import java.awt.Panel;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
public class Chat extends Frame {
private static final long serialVersionUID = 1L;
private List list = new List(6);
private TextField tip = new TextField(15);
private TextField tdata = new TextField(20);
DatagramSocket ds =null;
public Chat(){
this.add(list,"Center");
Panel p = new Panel();
this.add(p,"South");
p.setLayout(new BorderLayout());
p.add(tip,"West");
p.add(tdata,"East");
tip.setText("127.0.0.1");
try {
ds = new DatagramSocket(8888);
} catch (SocketException e) {
e.printStackTrace();
}
new Thread(new Runnable() {
public void run() {
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf, 1024);
try {
while(true){
ds.receive(dp);
System.out.println(new String(buf,0,dp.getLength()));
list.add(new String(buf,0,dp.getLength()));
// list.add(new String(buf,0,buf.length) +" from "+dp.getAddress().getHostAddress()+" : "+dp.getPort(), 0);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
tdata.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
try {
byte buf[];
buf = tdata.getText().getBytes();
System.out.println(buf.length);
ds.send(new DatagramPacket(buf, buf.length, InetAddress.getByName(tip.getText()), 8888));
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
tdata.setText("");
}
});
this.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent w) {
dispose();
System.exit(0);
}
});
}
public static void main(String[] args) {
Chat chat = new Chat();
chat.setSize(300, 400);
chat.setLocation(300, 200);
chat.setVisible(true);
chat.setResizable(false);
}
}
(只有UDP才能发送广播地址)
TCP 网络程序
TCP 网络程序的工作原理
TCP客户端程序与TCP报务器端程序的交互过程:
(1)服务器程序创建一个ServerSocket,然后调用accept方法等待客户来连接.
(2)客户端程序创建一个Socket并请求与服务器建立连接。
(3)服务器接收客户的连接请求,并创建一个新的Socket与该客户建立专线连接
(4)建立了连接的两个Socket在一个单独的线程(由服务器程序创建)上对话.
(5)服务器开始等待新的连接请求,当新的连接请求到达时,重复步骤(2)到步骤(5)的过程。
ServerSocket
ServerSocket() 创建非绑定服务器套接字。
ServerSocket(int port) 创建绑定到特定端口的服务器套接字。
ServerSocket(int port, int backlog) 利用指定的 backlog 创建服务器套接字并将其绑定到指定的本地端口号。
ServerSocket(int port, int backlog, InetAddress bindAddr) 使用指定的端口、侦听 backlog 和要绑定到的本地 IP 地址创建服务器。
close() 关闭此套接字。
accept() 侦听并接受到此套接字的连接。
Socket
Socket() 通过系统默认类型的 SocketImpl 创建未连接套接字
Socket(InetAddress address, int port) 创建一个流套接字并将其连接到指定 IP 地址的指定端口号。
Socket(InetAddress address, int port, InetAddress localAddr, int localPort) 创建一个套接字并将其连接到指定远程地址上的指定远程端口。
Socket(String host, int port) 创建一个流套接字并将其连接到指定主机上的指定端口号。
Socket(String host, int port, InetAddress localAddr, int localPort) 创建一个套接字并将其连接到指定远程主机上的指定远程端口。
getInputStream() 返回此套接字的输入流。
getOutputStream() 返回此套接字的输出流。
简单的TCP服务程序
1。TCP服务程序必须先启动运行,TCP客户机程序才能连接上TCP报务器程序。
2。使用Windows提供的telnet程序测试TCP服务器程序。
3。使用BufferedReader包装类,从网络输入流中一次读取一行文本。
4。如何打开telnet程序的本地回显功能。
windows DOS窗口输入telnet 地址 端口 (测试)
实例1
package com.cn;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Servers {
public static void main(String[] args) {
try {
ServerSocket s = new ServerSocket(8888);
Socket c = s.accept();
InputStream in = c.getInputStream();
OutputStream out = c.getOutputStream();
out.write("welcom to China\t".getBytes());
BufferedReader br=new BufferedReader(new InputStreamReader(in));
System.out.println(br.readLine());
in.close();
out.close();
c.close();
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
实例2 TCP网络聊天程序
package com.cn;
import java.awt.BorderLayout;
import java.awt.Frame;
import java.awt.List;
import java.awt.Panel;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
public class TCPChat extends Frame {
private static final long serialVersionUID = 1L;
private List list = new List(6);
private TextField tip = new TextField(15);
private TextField tdata = new TextField(20);
private ServerSocket ss = null;
private Socket socket=null;
private Socket client = null;
private BufferedReader br;
private PrintWriter out;
public TCPChat(){
this.add(list,"Center");
Panel p = new Panel();
this.add(p,"South");
p.setLayout(new BorderLayout());
p.add(tip,"West");
p.add(tdata,"East");
tip.setText("127.0.0.1");
try {
ss = new ServerSocket(8888);
} catch (IOException e) {
e.printStackTrace();
}
new Thread(new Runnable() {
public void run() {
while(true){
try {
client = ss.accept();
br = new BufferedReader(new InputStreamReader(client
.getInputStream()));
list.add(br.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
}
}).start();
tdata.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
try {
socket=new Socket(tip.getText(),8888);
out=new PrintWriter(socket.getOutputStream(),true);
out.println(tdata.getText());
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
tdata.setText("");
}
});
this.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent w) {
dispose();
System.exit(0);
}
});
}
public static void main(String[] args) {
TCPChat chat = new TCPChat();
chat.setSize(300, 400);
chat.setLocation(300, 200);
chat.setVisible(true);
chat.setResizable(false);
}
}
实例3 (服务与多个客户端会话)
package com.cn;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Servers {
public static void main(String[] args) {
try {
ServerSocket s = new ServerSocket(8888);
Boolean RUN = true;
while(RUN){
Socket c = s.accept();
Thread t =new Thread(new Severlet(c));
t.start();
}
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
package com.cn;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
public class Severlet implements Runnable {
private Socket c;
public Severlet(Socket c){
this.c = c;
}
public void run() {
try {
InputStream in = c.getInputStream();
OutputStream out = c.getOutputStream();
BufferedReader br =new BufferedReader(new InputStreamReader(in));
PrintWriter p =new PrintWriter(out,true);
while(true){
String strLine = br.readLine();
if(strLine.equalsIgnoreCase("quit")) break;
System.out.println(strLine);
String strEcho = new StringBuffer(strLine).reverse().toString();
p.println(strLine + "-->>" + strEcho);
}
br.close();
p.close();
c.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
如何检测和解决端口冲突问题
1、使用netstat命令查看当前正在被使用的TCP端口号。(netstat -na)
2、通过一个配制参数来指定TCP服务程序所使用的端口。
3、将用户指定的端口号保存到一个文件中,当服务器程序下次启动运行时,直接从文件中读取那个端口号。
TCP客户端程序
package com.cn;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client {
public static void main(String args[]){
try {
Socket c = new Socket("127.0.0.1",8888);
InputStream in =c.getInputStream();
OutputStream out = c.getOutputStream();
BufferedReader bc =new BufferedReader(new InputStreamReader(in));
PrintWriter pr = new PrintWriter(out,true);
BufferedReader br =new BufferedReader(new InputStreamReader(System.in));
while(true){
String strech = br.readLine();
pr.println(strech);
if(strech.equalsIgnoreCase("quit")) break;
System.out.println(bc.readLine());
}
br.close();
bc.close();
c.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
在TCP网络连接上传递对象
1、ObjectInputStream和ObjectOutputStream可以从底层输入流中读取对象类型的数据和将对象数据写入到底层输出流。
2、ObjectInputstream和ObjectOutputstream来包装底层网络字节流,TCP服务器和TCP客户端之间就可以传递对象类型的数据。
3、编程实例:(通过网络传输Java对象)
package com.cn;
public class Student implements java.io.Serializable{
private static final long serialVersionUID = 1L;
private int id;
private String name;
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package com.cn;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String args[]){
try {
ServerSocket s =new ServerSocket(8888);
Socket c = s.accept();
OutputStream out = c.getOutputStream();
ObjectOutputStream ot = new ObjectOutputStream(out);
Student sdt = new Student();
sdt.setId(1);
sdt.setName("张三");
sdt.setAge(20);
ot.writeObject(sdt);
ot.close();
out.close();
c.close();
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
package com.cn;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client {
public static void main(String[] args) {
try {
Socket c = new Socket("127.0.0.1",8888);
InputStream in = c.getInputStream();
ObjectInputStream oin = new ObjectInputStream(in);
Student std = (Student) oin.readObject();
System.out.println("学号:"+std.getId()+"\n性名:"+std.getName()+"\n年龄:"+std.getAge());
oin.close();
in.close();
c.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
访问Internet网络资源
java.net包中还有URL、URLDecoder、URLEncoder、URLConnection、HttpURLConnection等类。
URL(Uniform Resure Locator统一资源定位符)
1、URL的基本组成:协议、主机名、端口号、资源名。
2、URL编码规则:
将空格转换为加号(+)。
对0~9,a~z,A~Z之间的字符保持不变。
对于所其它的字符,有这个字符的当前字符集编码在内存中的十六进制
格式表示,并在每个字节前加上一个百分号(%)。如字符“+”用%2B表示
,字符“=”用%3D表示,字符“&”用%26表示,每个中文字符在内存中占两个
字节,字符“中”用%D6%D0表示,字符“国”用%B9%FA表示。
3、java.net包中提供了URLEncoder和URLecoder这两个类,来实现URL编码和解码。
HTTP协议
TTTP协议的会话过程
基于HTTP 1.0协议的客户机与服务器的信息交换过程(客户机--建立连接--发送请求信息——》服务器--发出响应信息--关闭连接--》客户机);
基于HTTP 1.1协议的客户机与服务器的信息交换过程(客户机--建立连接--发出第1~n次连接-》服务器--发出第1~n次连接--关闭连接--》客户机);
HTTP请求消息 一个完整的请求消息包括:一个请求行、若干消息头、以及实体内容。
一个完整的响应消息包括:一个状态行、若干消息头、以及体内容。
几个HTTP消息头
1、Connection 用于指定处理完本次请求/响应后,客户端与服务器是否继续保持连接,设置值可以为keep-Alive和close.
2、Accept-Language 用于指定客户机期望服务器返回的文档所使用的语言,可以指定多个以逗号分隔的国家语言。
3、Content-Length 用于表示实体内容的长度(字节数)。
4、Range 用于指定服务器只需返回文档中的部分内容及内容范围,有以下几种使用格式:
Range:bytes=100-599
Range:bytes=100-
Range:bytes=-100
5、Content-Range 用于指定服务器返回的部分实体内容的位置信息,例如:Content-Range:bytes 2543-4531/7898
telnet www.g.cn 80
GET / HTTP/1.1
Hosst:
Accept-Language: zh-cn
URL类
构造函数(都可能引发MalformedURLException异常):
URL(String spec) 根据 String 表示形式创建 URL 对象。
URL(String protocol, String host, int port, String file) 根据指定 protocol、host、port 号和 file 创建 URL 对象。
URL(String protocol, String host, int port, String file, URLStreamHandler handler) 根据指定的 protocol、host、port 号、file 和 handler 创建 URL 对象。
URL(String protocol, String host, String file) 根据指定的 protocol 名称、host 名称和 file 名称创建 URL。
URL(URL context, String spec) 通过在指定的上下文中对给定的 spec 进行解析创建 URL。
URL(URL context, String spec, URLStreamHandler handler) 通过在指定的上下文中用指定的处理程序对给定的 spec 进行解析来创建 URL。
工厂设计模式
URL类的setURLStreamHandlerFactory(URLStreamHandlerFactory fac)设置应用程序的 URLStreamHandlerFactory。在一个给定的 Java 虚拟机中,此方法最多只能调用一次。
URLStreamHandlerFactory类的createURLStreamHandler(String protocol) 创建具有指定协议的新 URLStreamHandler 实例。
URLConnetion和HttpURLConnetin类
通过在 URL 上调用 openConnection 方法创建连接对象。
处理设置参数和一般请求属性。
使用 connect 方法建立到远程对象的实际连接。
远程对象变为可用。远程对象的头字段和内容变为可访问。
setRequestProperty(String key, String value) 设置一般请求属性。
getHeaderFields() 返回头字段的不可修改的 Map。
getInputStream() 和 getOutputStream() 返回从此打开的连接读取的输入出流
getHeaderField(int n) 返回第 n 个头字段的值。
getHeaderField(String name) 返回指定的头字段的值。
getContentLength() 返回 content-length 头字段的值。
getContentEncoding() 返回 content-encoding 头字段的值。
getContentType() 返回 content-type 头字段的值。
一个HTTP连接可以被多个HttpUPLConnection实例对象共享,调用HttpURLConnection的disconnect方法可以关闭底层共享网络。
实例:
package com.cn;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class GetGoogle {
public static void getConterByLanguage(String country){
try {
URL urlGoogle = new URL("http://www.google.com");
HttpURLConnection googleConnection =
(HttpURLConnection) urlGoogle.openConnection();
googleConnection.setRequestProperty("Accept-Language" , country);
Map requests = googleConnection.getRequestProperties();
Set reqFields = requests.keySet();
Iterator itrReq = reqFields.iterator();
while(itrReq.hasNext()){
String field = (String) itrReq.next();
System.out.println(field + " : " +
googleConnection.getRequestProperty(field));
}
googleConnection.connect();
Map responses = googleConnection.getHeaderFields();
Set resFields = responses.keySet();
Iterator itrRes = resFields.iterator();
while(itrRes.hasNext()){
String field = (String) itrRes.next();
System.out.println(field + " : " +
googleConnection.getHeaderField(field));
}
InputStream is = googleConnection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String strLine = null;
while((strLine = br.readLine()) != null){
System.out.println(strLine);
}
br.close();
googleConnection.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (ProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
System.out.println("获取日文页面");
getConterByLanguage("ja");
System.out.println("\n");
System.out.println("获取中文页面");
getConterByLanguage("zh-cn");
}
}