网络编程
一、什么是网络
1.1概念
- 由点和线构成,表示多个对象间的相互联系
1.2计算机网络
-
为了实现资源共享和信息传递,通过通信线路连接起来的若干主机(Host)
-
常见的计算机网络
- 互联网:点与点之间相连
- 万维网:端与端之间相连
- 物联网:物与物之间相连
- 网络编程:让计算机与计算机之间进行建立连接,实现通信
1.3网络模型
- OSI参考模型
- OSI:开放式系统互联
- 是ISO组织再21985年研究的网络互联模型
- 体系结构的标准定义了网络互联的七层框架
- OSI:开放式系统互联
-
每层功能:
-
第七层:应用层负责文件访问和管理、可靠运输服务、远程操作服务(HTTP、 FTP、 SMTP)
-
第六层:表示层负责定义转换数据格式及加密,允许选择以二进制或ASCI格式传输
-
第五层:会话层负责使应用建立和维持会话,使通信在失效时继续恢复通信(断点续传)
-
第四层:传输层负责是否选择差错恢复协议、数据流重用、错误顺序重排(TCP、 UDP)
-
第三层:网络层负责定义了能够标识所有网络节点的逻辑地址。 (IP地址)
-
第二层:链路层在物理层上,通过规程或协议(差错控制)来控制传输数据的正确性。(MAC)
-
第一层:物理层为设备之间的数据通信提供传输信号和物理介质。(双绞线、 光导纤维)
-
-
TCP/IP模型
- TCP/IP模型是因特网使用的参考模型,基于TCP/IP的参考模型将协议分成四个层次
- 该模型最重要的两个协议就是TCP/IP协议
- 每层功能:
- 应用层:负责传输各种最终形态的数据,是直接与用户交互的层,典型的协议有HTTP、FTP(文件传输协议)
- 传输层:负责传送文本数据,主要协议是TCP、UDP协议
- 网络层:负责分配地址和传送二进制数据,主要协议是IP协议
- 网络接口层:负责建立电路连接,是整个网络的物理基础,典型的协议包括以太网、ADSL(拨号上网)等
1.4网络编程总结
- 什么是计算机网络
- 为了实现资源共享和信息传递,通过传输介质将若干主机连接到一起的网络
- 计算机网络模型
- OSI:
- 应用层 主要指的是程序
- 表示层 将数据加密或者解密转换成二进制数据
- 会话层 保持主机与主机之间的连接
- 传输层 通过网络协议传输数据(TCP/UDP协议)
- 网络层 分配IP地址
- 数据链路层 保证准确性(MAC地址 物理地址)
- 物理层 进行数据传输
- TCP/IP模型
- 应用层
- 传输层
- 网络层
- 网络接口层
- OSI:
- 网络编程需要什么
- 通信协议(TCP、UDP、HTTP)
- IP地址
- 端口号
- 网络编程三要素:协议、地址、端口号
1.5 TCP/UDP
-
TCP协议: Transmission Control Protocol传输控制协议
- 是一种面向连接的、可靠的、基于字节流的传输层通信协议。数据大小无限制。建立连接的过程需要三次握手,断开连接的过程需要四次挥手
-
UDP协议: User Datagram Protocol用户数据报协议
- 是一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务,每个包的大小64KB
1.6 IP
-
IP协议: Internet Protocol Address互联网协议地址/网际协议地址
- 分配给互联网设备的数字标签(唯一标识)
-
IP地址分为两种:
- IPV4: 4字节32位整数,并分成4段8位的二进制数,每8位之间用圆点隔开,每8位整数可以转换为一个0~255的十进制整数
- 格式: D.D.D.D
- 例如: 255.255.255.255
- IPV6: 16字节128位整数,并分成8段十六进制数,每16位之间用圆点隔开,每16位整数可以转换为一个0~65535的十进制数
- 格式: X.X.X.X.X.X.X.X
- 例如: FFFF.FFFF.FFFF.FFFF.FFFF.FFFF.FFFF.FFFF
- IPV4: 4字节32位整数,并分成4段8位的二进制数,每8位之间用圆点隔开,每8位整数可以转换为一个0~255的十进制整数
-
IPV4的应用分类
- A类:政府机构,1.0.0.1 ~ 126.255.255.254
- B类:中型企业,128.0.0.1 ~ 191 .255.255.254
- C类:个人用户,192.0.0.1 ~ 223.255.255.254
- D类:用于组播,224.0.0.1 ~ 239.255.255.254
- E类:用于实验,240.0.0.1 ~ 255.255.255.254
- 回环地址: 127.0.0.1, 指本机,一般用于测试使用
- 查看IP命令: ipconfig
- 测试IP命令: ping D.D.D.D
-
DNS 域名解析 将域名解析成IP地址一个域名只能对应一个ip地址 一个ip地址可以对应多个域名
1.7 InetAddress
类
- 概念:表示互联网协议(IP) 地址对象,封装了与该IP地址相关的所有信息并提供获取信息的常用方法。
- 常用方法:
public static InetAddress getLocalHost()
获得本地主机地址对象public static InetAddress getByName(String host)
根据主机名称获得地址对象public static InetAddress[] getAllByName(String host)
获得所有相关地址对象public String getHostAddress()
获取IP地址字符串public String getHostName()
获得IP地址主机名
二、端口号
2.1概述
-
网络编程三要素之端口号:
-
概念:
- 端口号是之每一个设备程序的唯一数字标识
-
端口分类:
- 公认端口: 0~1023
- 注册端口: 1024~49151
- 动态或私有端口: 49152~65535
-
常用端口:
- MySql: 3306
- Oracle: 1521
- redis:6379
- Tomcat: 8080
- SMTP: 25
- Web服务器: 80
- FTP服务器: 21
-
总结:
- 以后自己写的程序端口号最好设置在1024-65535之间
三、通信协议
3.1概述
-
概念:
-
TCP:传输协议
- 特点:面向连接,安全可靠,效率低,基于字节流进行通信,数据大小无限制 建立连接三次握手,断开连接四次挥手
-
UDP:数据报协议
- 特点:面向无连接,不安全,基于数据包的形式通信,数据包大概在64kb
-
四、基于TCP协议通信
4.1案例1
- 通过客户端向服务端发送
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
public class Client {
public static void main(String[] args) throws IOException {
//建立客户端对象
Socket socket = new Socket("localhost", 999);
//通过socket对象创建输出流
OutputStream out = socket.getOutputStream();
//通过输出流写出内容到服务端
out.write("hello".getBytes());
//释放资源
out.close();
socket.close();
}
}
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws IOException {
//创建服务端Socket对象
ServerSocket ss =new ServerSocket(999);
//通过new ServerSocket对象获取Socket对象
System.out.println("服务端已启动");
Socket socket = ss.accept();
//当客户端发送数据到客户端才会执行
//通过Socket对象获取输入流
InputStream in = socket.getInputStream();
//通过输入流读取数据
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf))!=-1){
String str =new String(buf,0,len);
System.out.println(str);
}
//释放资源
in.close();
socket.close();
ss.close();
}
}
案例二 基于TCP协议多线程通信
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;
public class Client {
public static void main(String[] args) throws IOException {
Scanner sc = new Scanner(System.in);
while (true) {
//创建客户端Socket对象
Socket socket = new Socket("localhost", 9898);
//创建输出流对象
OutputStream out = socket.getOutputStream();
//通过输出流写数据
String words = sc.next();
if(words.equals("886")){
break;
}
//将用户输入的信息转化成字节
out.write(words.getBytes());
out.close();
socket.close();
}
sc.close();
}
}
java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args)throws Exception {
//创建服务端Socket对象
ServerSocket ss = new ServerSocket(9898);
//创建Socket对象
System.out.println("服务端已启动");
while (true) {
//阻塞式方法 来一个创建一个
Socket socket = ss.accept();
String ip = socket.getInetAddress().getHostAddress();
new Thread(new Runnable() {
@Override
public void run() {
try {
InputStream in = socket.getInputStream();
//读取客户端发送的数据
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line;
while ((line=br.readLine())!=null){
System.out.println(ip+":"+line);
}
br.close();
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
}
}
案例三
- 实现客户端文件上传功能
import java.io.*;
import java.net.Socket;
public class Client {
public static void main(String[] args) throws IOException {
//实现上传功能
//创建Socket对象
Socket socket = new Socket("localhost", 9897);
//创建输出流
OutputStream out = socket.getOutputStream();
//模拟文件上传fis指的是上传的文件
FileInputStream fis = new FileInputStream("C:\\Users\\24826\\Desktop\\a.jpg");
byte[] buf = new byte [1024];
int len;
while ((len=fis.read(buf))!=-1){
out.write(buf,0,len);
}
//告知服务器写完了
socket.shutdownOutput();
//服务短返回上传成功
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println(br.readLine());
//释放资源
fis.close();
out.close();
socket.close();
}
}
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.UUID;
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(9897);
while (true) {
Socket socket = ss.accept();
new Thread(new Runnable() {
@Override
public void run() {
try {
InputStream in = socket.getInputStream();
//文件重名问题 1.时间戳+5位随机数(时间的毫秒数)2.UUID 3.雪花算法
String fileName = UUID.randomUUID().toString().replace("-", "");
FileOutputStream fos = new FileOutputStream(fileName + ".jpg");
byte[] buf = new byte[1024];
int len;
while ((len=in.read(buf))!=-1){
fos.write(buf,0,len);
}
OutputStream out = socket.getOutputStream();
out.write("上传成功".getBytes());
out.close();
fos.close();
in.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
//解决文件重名问题
}
}).start();
}
}
}
五、基于UDP协议通信
5.1案例
- 发送端发送数据到接收端
import java.io.IOException;
import java.net.*;
public class Send {
public static void main(String[] args) throws IOException {
//基于UDP协议创建Socket对象 无序指定端口号协议
DatagramSocket ds = new DatagramSocket();
//2.创建数据包对象
byte[] buf = "你好接收端".getBytes();
DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress.getByName("localhost"), 9999);
//发送数据包
ds.send(dp);
//释放资源
ds.close();
}
}
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class Receive {
public static void main(String[] args) throws Exception{
//1.基于UDP协议创建Socket对象
DatagramSocket ds = new DatagramSocket(9999);
//2.创建数据包对象
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf, buf.length);
//3.接受数据包
ds.receive(dp);
//4.解析数据包数据
//从数据包中获取数据
byte[] data = dp.getData();
//从数据包中获取InetAddress对象
InetAddress inetAddress = dp.getAddress();
//从数据包中获取端口号
int port = dp.getPort();
//获取数据包的数据字节长度
int length = dp.getLength();
String str = new String(data, 0, length);
System.out.println("ip"+inetAddress.getHostAddress());
System.out.println("port"+port);
System.out.println("data"+data);
//5.释放资源
ds.close();
}
}
六、基于HTTP协议通信
6.1案例1
- 通过HTTP协议下载图片到本地
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.UUID;
public class Demo01 {
public static void main(String[] args) throws IOException {
//实现使用http协议通信 从服务端下载一张图片
//创建URL对象
URL url = new URL("https://img10.360buyimg.com/cms/jfs/t1/115449/27/29260/131972/631902deE0c0f8dab/9288fcd9d35fddde.jpg");
//通过服务器连接对象
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
//判断连接是否成功
if (connection.getResponseCode()==200){
//获取输入流对象
InputStream in = connection.getInputStream();
FileOutputStream fos = new FileOutputStream("download\\" + UUID.randomUUID().toString().replace("-", "")+".jpg");
byte[] buf = new byte[1024];
int len;
while ((len=in.read(buf))!=-1){
fos.write(buf,0,len);
}
System.out.println("success");
//释放资源
fos.close();
in.close();
connection.disconnect();
}
}
}
connection.getInputStream();
FileOutputStream fos = new FileOutputStream("download\\" + UUID.randomUUID().toString().replace("-", "")+".jpg");
byte[] buf = new byte[1024];
int len;
while ((len=in.read(buf))!=-1){
fos.write(buf,0,len);
}
System.out.println("success");
//释放资源
fos.close();
in.close();
connection.disconnect();
}
}
}