第一章 网络编程概述
- 网络编程概述
Java语言提供了网络的支持,程序员能够很容易的开发常见的网络应用.Java提供的类库,可以实现无痛的网络连接,联网的底层细节被隐藏在安装Java本机系统里.由JVM进行控制.并且Java实现了一个跨平台的网络库.
- 网络编程的目的
直接或间接地通过网络协议与其它计算机进行通讯,实现资源的共享
- 网络编程中面临的主要问题
1. 如何准确地定位网络上一台或多台主机2. 找到主机后如何可靠高效地进行数据传输
第二章 网络通信要素
第1节 通信双方地址(通信要素1)
通讯要素1:IP地址 和 端口号
- IP地址
Java语言提供了InetAddress类用来描述主机信息(IP地址和域名)
IP地址:标识Internet上的计算机 比如百度服务器的IP地址 220.181.38.251
域名: 计算机的定位标识,由于IP地址不方便记忆,所以可以通过域名映射IP地址,理论上和IP同等功效.
为了标识自己本地主机所以计算机为每一个自己的主机也设置了IP地址和域名(127.0.0.1和localhost),称之为回环地址.
InetAddress: 表示互联网协议 (IP) 地址,有两个典型子类Inet4Address(IPv4地址)和Inet6Address(IPv6地址)
常见方法:
//通过主机名获取主机的InetAddress对象
InetAddress ia = InetAddress.getByName("baidu.com");
System.out.println(ia);//baidu.com/220.181.38.251
//获取主机地址
String address = ia.getHostAddress();
System.out.println(address);//220.181.38.251
//获取主机名称
String name = ia.getHostName();
System.out.println(name);//baidu.com
- 端口号
标识正在计算机上运行的进程;同的进程有不同的端口号;计算机的端口号被规定为一个16位的整数,取值范围为0~65535个.0~1023被服务器占用,我们在编写网络应用时应该使用1024~65535端口号,以免发生端口冲突.
- 端口号和IP地址组合
端口号与IP地址的组合得出一个网络套接字.
第2节 通信规则(通信要素2)
计算机网络中实现通信必须有一些约定,即通信协议.对传输频率,数据格式,传输步骤,出错控制等设计的标准.
- 网络通信协议模型
OSI参考模型: 模型过于理想化,未能在因特网上进行广泛推广。TCP/IP参考模型(TCP/IP协议): 事实上的国际标准。
- 协议模型差异化
OSI参考模型 | TCP/IP参考模型 | TCP/IP参考模型各层对应协议 |
应用层 | 应用层 | HTTP、ftp、telnet、DNS… |
表示层 | ||
会话层 | ||
传输层 | 传输层 | TCP、UDP、… |
网络层 | 网络层 | IP、ICMP、ARP… |
数据链路层 | ||
物理层 | 物理+数据链路层 | Link |
- 数据封装和数据拆分
- TCP/IP协议簇
TCP/IP协议簇是Internet的基础,也是当今最流行的组网形式.TCP/IP是一组协议的代名词,包括许多别的协议,组成了TCP/IP协议簇.其中比较重要的有PPP协议、IP协议、TCP协议、UDP协议、FTP协议、DNS协议、SMTP协议等 |
第三章 TCP网络通信
第1节 TCP介绍
1. 使用TCP协议前,须先建立TCP连接,形成传输数据通道2. 传输前,采用"三次握手"方式,是可靠的3. TCP协议进行通信的两个应用进程:客户端、服务端4. 在连接中可进行大数据量的传输5. 传输完毕,需释放已建立的连接,效率低(释放连接需要四次挥手)
三次握手建立TCP连接通道
第1次 客户端向服务器端发送数据,服务器端收到了,然后服务器端返回给客户端一个信息第2次 客户端接收到服务器端返回的消息(到这里可以知道服务器端可以正确接收和处理客户端消息消息)第3次 客户端接收到服务器端返回来的消息之后,告诉服务器端我已经接收到了你响应给我的消息.以上三步完成之后才能证明服务器端和客户端都可以正确接收和处理消息.如果只有1、2步只能证明服务器端正常不能证明客户端正常.
四次挥手释放TCP连接通道
第1次 客户端和服务器端说我要关闭连接了第2次 服务器端说可以,但是你等我一会,我把剩余的任务做完第3次 服务器端做完收尾工作之后和客户端说,我这边结束了,你可以关了第4次 客户端说OK,我关了
第2节 Socket介绍
- Socket介绍
1. 利用套接字(Socket)开发网络应用程序早已被广泛的采用,以至于成为事实上的标准2. 通信的两端都要有Socket,是两台机器间通信的端点3. 网络通信其实就是Socket间的通信4. Socket允许程序把网络连接当成一个流,数据在两个Socket间通过IO传输5. 一般主动发起通信的应用程序属客户端,等待通信请求的为服务端
- Socket类
方法 | 功能 |
void close() | 关闭Socket,不可在以后的网络连接中使用,除非创建新的套接字 |
InputStream getInputStream() | 获取与Socket相关联的字节输入流,用于从Socket中读数据 |
OutputStream getOutputStream() | 获取与Socket相关联的字节输出流,用于向Socket中写数据 |
- ServerSocket类
方法 | 功能 |
Socket accept() | 等待客户端的连接请求,返回与该客户端进行通信用的Socket对象 |
void close() | 关闭监听Socket |
第3节 基于Socket编程实现cs(client-server)
- 案例一(实现客户端向服务器端发送一段数据)
//服务器端
public class Server {
public static void main(String[] args) throws IOException {
//创建服务器端套接字
ServerSocket ss = new ServerSocket(6666);
System.out.println("服务器端已启动,等待客户端连接....");
//获取服务器端套接字,并监听,等待客户端发送数据
Socket socket = ss.accept();
//如果客户端发送过来了数据,获取数据
InputStream in = socket.getInputStream();
byte[] buff = new byte[1024];
int len = in.read(buff);
System.out.println("接受客户端发送的数据为:"+ new String(buff,0,len));
socket.close();
ss.close();
}
}
//客户端
public class Client {
public static void main(String[] args) throws IOException {
//创建客户端套接字
Socket socket = new Socket("127.0.0.1", 6666);
//获取套接字输出流
OutputStream out = socket.getOutputStream();
//向通道中写入数据
String msg = "Hello Socket";
out.write(msg.getBytes());
socket.close();
}
}
- 案例二(实现双向数据)
//服务器端
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(6666);
System.out.println("服务器端已启动,等待客户端连接....");
Socket socket = ss.accept();
InputStream in = socket.getInputStream();
byte[] buff = new byte[1024];
int len = in.read(buff);
System.out.println("我是服务器端-->接收客户端数据为:"+new String(buff,0,len));
System.out.println("给客户端返回消息开始...");
//给客户端响应一个接收成功的消息
String msg = "服务器端接收数据成功";
OutputStream out = socket.getOutputStream();
out.write(msg.getBytes());
//关闭
socket.close();
ss.close();
}
}
//客户端
public class Client {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1", 6666);
OutputStream out = socket.getOutputStream();
//发送的消息
String msg = "我是客户端消息";
out.write(msg.getBytes());
//接收服务器端数据
InputStream in = socket.getInputStream();
byte[] buff = new byte[1024];
int len = in.read(buff);
System.out.println("我是客户端-->接收服务器端数据为:"+new String(buff,0,len));
socket.close();
}
}
- 案例三(客户端给服务器端发送一张图片,服务器端将图片保存到本地,并且告诉客户端数据上传成功)
//服务器端
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(6666);
System.out.println("服务器端已启动,等待客户端连接....");
Socket socket = ss.accept();
System.out.println("服务器端已启动,客户端连接成功....");
InputStream in = socket.getInputStream();
byte[] buff = new byte[512];
int len = 0;
System.out.println("连接成功,接收来自客户端数据开始....");
FileOutputStream fout = new FileOutputStream("pic.png");
while((len=in.read(buff))!=-1) {
fout.write(buff, 0, len);
}
System.out.println("连接成功,接收来自客户端数据完成....");
System.out.println("给客户端返回消息开始...");
//给客户端响应一个接收成功的消息
String msg = "服务器端接收数据成功";
OutputStream out = socket.getOutputStream();
out.write(msg.getBytes());;
//关闭
out.close();
fout.close();
in.close();
socket.close();
ss.close();
}
}
//客户端
public class Client {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1", 6666);
OutputStream out = socket.getOutputStream();
//读取本地文件
FileInputStream fin = new FileInputStream("/Users/hushuang/Downloads/wangluobaincheng.png");
byte[] fbuff = new byte[128];
int flen=0;
while((flen=fin.read(fbuff))!=-1) {
out.write(fbuff, 0, flen);
}
//数据发送完毕
socket.shutdownOutput();
//接收服务器端数据
InputStream in = socket.getInputStream();
byte[] buff = new byte[1024];
int len = in.read(buff);
System.out.println("我是客户端-->接收服务器端数据为:"+new String(buff,0,len));
in.close();
fin.close();
out.close();
socket.close();
}
}
第四章 UDP网络通信
第1节 UDP介绍
类DatagramSocket和DatagramPacket实现了基于UDP协议网络程序
UDP数据报通过数据报套接字DatagramSocket发送和接收
系统不保证UDP数据报一定能够安全送到目的地,也不能确定什么时候可以抵达
DatagramPacket对象封装了UDP数据报,在数据报中包含了发送端的IP地址和端口号以及接收端的IP地址和端口号
UDP协议中每个数据报都给出了完整的地址信息,因此无须建立发送方和接收方的连接
第2节 UDP实现
运行流程:
1. DatagramSocket与DatagramPacket
2. 建立发送端,接收端
3. 建立数据包
4. 调用Socket的发送、接收方法
5. 关闭Socket
发送端与接收端是两个独立的运行程序
- 发送端
public class Send {
public static void main(String[] args) throws IOException {
DatagramSocket ds = new DatagramSocket();
byte[] bs = "Hello UDP".getBytes();
//封装数据报
DatagramPacket dp = new DatagramPacket(bs,0,bs.length,InetAddress.getByName("127.0.0.1"),10000);
//发送
ds.send(dp);
ds.close();
}
}
- 接收端
public class Receive {
public static void main(String[] args) throws IOException {
DatagramSocket ds = new DatagramSocket(10000);
byte[] by = new byte[1024];
DatagramPacket dp = new DatagramPacket(by,by.length);
//接收
ds.receive(dp);
String str = new String(dp.getData(),0,dp.getLength());
System.out.println(str);
ds.close();
}
}
第五章 URL编程
第1节 URL概述
- URL介绍
URL(Uniform Resource Locator):统一资源定位符,它表示 Internet 上某一资源的地址.通过URL我们可以访问 Internet 上的各种网络资源,比如最常见的 www,ftp 站点.浏览器通过解析给定的 URL 可以在网络上查找相应的文件或其他资源 |
- URL组成
URL的基本结构由5部分组成<传输协议>://<主机名>:<端口号>/<文件名>例如: http://192.168.1.100:8080/taobao/index.html
第2节 URL常见API
- 构造方法
方法 | 介绍 |
URL(String spec) | 根据 String 表示形式创建 URL 对象;spec:域名 |
1 | URL url = new URL ("http://www.baidu.com/index.html"); |
- 常见方法
方法 | 介绍 |
getProtocol() | 获取此URL 的协议名称 |
getHost() | 获取该URL的主机名 |
getPort() | 获取该URL的端口号 |
getPath() | 获取该URL的文件路径 |
getFile() | 获取该URL的文件名 |
getRef() | 获取该URL在文件中的相对位置 |
getQuery() | 获取该URL的查询名 |
- 案例一
public class TestDemo {
public static void main(String[] args) throws IOException {
URL url = new URL("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fwww.petking.cn%2Fupload%2F20200505%2Fe8120b1111d8badc952a035d0b927b8c.jpg&refer=http%3A%2F%2Fwww.petking.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1638798637&t=7b6aa84c4d3ad92708d4ced882a5d976");
InputStream in = url.openStream();
FileOutputStream out = new FileOutputStream("/Users/hushuang/Downloads/123.jpg");
byte[] buff = new byte[1024];
int len=0;
while((len=in.read(buff))!=-1) {
out.write(buff, 0, len);
}
out.close();
in.close();
}
}