网络编程
- 概述:Java提供的网络类库,可以实现无痛的网络连接,联网的底层细节被隐藏在Java的本机安装系统里,由JVM进行控制,并且Java实现了一个跨平台的网络类库,程序员面对的是一个统一的网络编程环境。
- 网络编程目的:直接或间接地通过网络协议与其他计算机实现数据交换,进行通讯。
- 网络编程主要地两个问题:
- 如何准确地定位网络上的一台或多台主机,定位主机上的特定应用。
- 找到主机后如何可靠,高效地进行数据传输。
通信要素:
通信双方地址
IP地址与端口号的组合得出一个网络套接字:Socket。
IP地址
-
IP地址:唯一的标识Internet上的计算机(通信实体),在Java中使用InetAddress代表IP。 -
本地回路地址(hostAddress):127.0.0.1,主机名(hostName):localhost。 -
IP地址分类方式1:IPV4和IPV6
- IPV4:4个字节组成,四个0~255。
- IPV6:16个字节(128位),写成8个无符号整数,每个整数用4个十六进制位表示,数之间用“:”分开。
-
IP地址分类方式2:公网地址(万维网)和私有地址(局域网)。192.168.开头的就是私有地址,范围为:192.168.0.0~192.168.255.255。专门为组织机构内使用。由于IP不易记忆,所以可以用特定的域名指代本机IP,通过域名解析服务器(DNS),把域名解析成对应的IP地址。(先找本机hosts(C:\Windows\System32\drivers\etc\hosts),是否有输入的域名地址,如果没有的话,在通过DNS服务器,找主机)
端口号
- 端口号表示正在计算机上运行的进程(程序)。
- 端口号被规定为一个16位的整数:0~65535。
- 端口分类:
- 公认端口:0~1023。被预先定义的服务通信占用(如HTTP占用端口80,FTP占用端口21,Telnet占用端口23)。
- 注册端口:1024~49151。分配给用户进程或用户程序。(如Tomcat占用端口8080,MySQL占用端口3306)。
- 动态/私有端口:49152~65535。
网络通信协议:
- 应用层:提供应用程序的网络接口。
- 传输层:为两台主机间的应用程序提供端到端的通信。传输层从应用层接收数据,并且在必要的时候把他分成较小的单元,传递给网络层,并确保到达网络层的各段信息正确无误。
- 网络层:主要协议由IP、ICMP(互联网控制报文协议)、IGMP(互联网组管理协议)、ARP(地址解析协议)、RARP(反向地址解析协议)等,涉及寻址和路由器的选择。
- 物理层和数据链路层:涉及物理介质访问和二进制数据流传输。
在同层间可以通信,上一层可以调用下一层,而与在下一层不发生关系。各层互不影响,利于系统开发和扩展。
TCP/IP协议簇
- 传输控制协议TCP,用户数据报协议UDP。
- TCP/IP以其两个主要协议:传输控制协议(TCP)和网络互联协议(IP)而得名,但实际上是一组协议,包括多个具有不同功能且互为关联的协议。
- IP协议是网络层的主要协议,支持网间互联的数据通信。
TCP协议
- 使用TCP协议前,必须先建立TCP连接,形成数据传输通道。
- 传输前,采用“三次握手”的方式,进行点对点通信,是可靠的,不会造成数据丢失。
- TCP协议进行通信的两个应用进程:客户端,服务端。
- 在连接中可进行大数据量的传输。
- 传输完毕,须释放已建立的连接,效率低。
UDP协议
- 将数据,数据源,数据目的封装成数据报,不需要建立连接。
- 每个数据报的大小限制在64KB内。
- 发送不管对方是否准备好,接收方收到也不确认,所以不可靠,可能造成数据丢失。
- 可以广播发送。
- 发送数据结束时,无需释放资源,开销小,速度快。
- 类DatagramSocket和类DatagramPacket实现了基于UDP协议网络程序。
- UDP数据报通过数据报套接字DatagramSocket发送和接收,系统不保证UDP数据报一定能够安全送到目的地,也不确定什么时候抵达。
- DatagramPacket对象封装了UDP数据报,在数据报中包含了发送端的IP地址和端口号以及接收端的IP地址和端口号。
- UDP协议中每个数据报都给出了完整的地址信息,因此无需建立发送方和接收方的连接,如同发快递包裹一般。
URL类
URL:统一资源定位符,他表示Internet上某一资源的地址。
- 通过URL,我们可以访问Internet上的各种网络资源,比如常见的www站点,浏览器通过解析给定的URL可以在网络上查找相应的文件或其他资源。
- URL的基本结构:传输协议://主机名:端口号/文件名#片段名?参数列表
- 一个URL对象生成后,其属性是不能被改变的,但可以通过他给定的方法来获取属性。
常用方法:
- public String getProtocol():获取该URL的协议名。
- public String getHost():获取该URL的主机名。
- public String getPort():获取该URL的端口名。
- public String getPath():获取该URL的文件路径。
- public String getFile():获取该URL的文件名。
编程实例
TCP示例①:
客户端发送文件给服务端,服务端将文件保存在本地。
-
客户端:
- 确定服务器的IP地址和端口号
- 因为要发送文件给服务端,所以要读取客户端的文件,提高效率,使用缓冲流处理节点流
- 通过套接字的getOutputStream获取输出流
- 写出文件
- 关闭资源
-
服务器端:
- 设置端口号
- 因为要接受文件,所以调用accept(),表示可以进行文件的接收
- 通过getInputStream获取输入流,读取传送过来的文件
- 通过缓冲流对文件进行写出到硬盘中
- 写出文件到硬盘
- 关闭资源
代码:
public class TCPTest2 {
@Test
public void client() {
Socket soc = null;
BufferedInputStream bis = null;
OutputStream os = null;
BufferedOutputStream bos = null;
try {
InetAddress inet1 = InetAddress.getByName("127.0.0.1");
soc = new Socket(inet1, 9966);
bis = new BufferedInputStream(new FileInputStream("mm.jpg"));
os = soc.getOutputStream();
bos = new BufferedOutputStream(os);
byte[] buffer = new byte[1024];
int len;
while ((len = bis.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
@Test
public void server() {
ServerSocket ss = null;
Socket soc = null;
InputStream is = null;
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
ss = new ServerSocket(9966);
soc = ss.accept();
is = soc.getInputStream();
bis = new BufferedInputStream(is);
bos = new BufferedOutputStream(new FileOutputStream("mm1.jpg"));
byte[] buffer = new byte[1024];
int len;
while ((len = bis.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
}
TCP示例②:
从客户端发送文件给服务器端,服务器端保存到本地,并返回”发送成功“给客户端,并关闭相应的连接。
- 注意:客户端发送完文件后要调用shutdownOutput(),表明文件传输完成,停止传输,不然服务器端不确定是否已经还有文件需要接收。
public class TCPTest3 {
@Test
public void client() throws Exception{
Socket soc = new Socket(InetAddress.getByName("127.0.0.1"),9898);
OutputStream os = soc.getOutputStream();
FileInputStream fis = new FileInputStream("hello.txt");
byte[] buffer = new byte[5];
int len;
while ((len = fis.read(buffer)) != -1){
os.write(buffer,0,len);
}
soc.shutdownOutput();
InputStream is = soc.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer2 = new byte[5];
int len1;
while ((len1 = is.read(buffer2)) != -1){
baos.write(buffer2,0,len1);
}
System.out.println(baos);
baos.close();
is.close();
fis.close();
os.close();
soc.close();
}
@Test
public void server() throws Exception{
ServerSocket ss = new ServerSocket(9898);
Socket soc = ss.accept();
InputStream is = soc.getInputStream();
FileOutputStream fos = new FileOutputStream("hello1.txt");
byte[] buffer = new byte[5];
int len;
while ((len = is.read(buffer)) != -1){
fos.write(buffer,0,len);
}
OutputStream os = soc.getOutputStream();
os.write("发送成功".getBytes());
os.close();
fos.close();
is.close();
soc.close();
ss.close();
}
}
UDP示例
使用UDP进行数据传输
-
发送端:
- InetAddress指定接收端的IP地址
- 创建DatagramSocket对象用。
- 编写发送的内容
- 将数据用DatagramPacket对象进行封装,封装成数据报
- 发送数据报
- 关闭资源
-
接收端:
- 创建DatagramSocket对象指定自己的端口号
- 创建DatagramPacket对象用于存储接收的数据报
- 接收数据报
- 打印输出
- 关闭资源
代码:
public class UDPTest {
@Test
public void sender() {
DatagramSocket socket = null;
try {
InetAddress address = InetAddress.getByName("127.0.0.1");
socket = new DatagramSocket();
String str = "拿来吧你!";
byte[] data = str.getBytes();
DatagramPacket packet = new DatagramPacket(data,0,data.length,address,9999);
socket.send(packet);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (socket != null){
socket.close();
}
}
}
@Test
public void receiver() {
DatagramSocket socket = null;
try {
socket = new DatagramSocket(9999);
byte[] buffer = new byte[20];
DatagramPacket packet = new DatagramPacket(buffer,0,buffer.length);
socket.receive(packet);
System.out.println(new String(packet.getData(),0,packet.getLength()));
} catch (IOException e) {
e.printStackTrace();
} finally {
if (socket != null){
socket.close();
}
}
}
}
URL示例
URL编程从服务器端下载资源
- 创建URL对象,指定资源所在url地址
- 通过URl对象的openConnection()建立连接,注意协议的类型
- 读取文件并把文件写出到硬盘
- 关闭资源
public class URLTest {
@Test
public void ice() {
HttpURLConnection connection = null;
InputStream is = null;
FileOutputStream fos = null;
try {
URL url = new URL("https://vkceyugu.cdn.bspapp.com/VKCEYUGU-3f5ac434-77f3-4bf1-a1c6-ad1deeb5100a/015a8488-fd25-4c68-8e8a-d11c505b5851.png");
connection = (HttpURLConnection) url.openConnection();
connection.connect();
is = connection.getInputStream();
fos = new FileOutputStream("picture1.jpg");
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1){
fos.write(buffer,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
}
connection.disconnect();
}
}
|