网络编程
网络基础
OSI七层网络模型
OSI(Open System Interconnect)即开放式系统互联。 一般都叫OSI参考模型,是ISO(国际标准化组织)组织在1985年研究的网络互连模型。ISO为了更好的使网络应用更为普及,推出了OSI参考模型。
应用层
OSI参考模型中最靠近用户的一层,是为计算机用户提供应用接口,也为用户直接提供各种网络服务。我们常见应用层的网络服务协议有:HTTP,HTTPS,FTP,POP3、SMTP等。(APP中用户看到的数据)
表示层
表示层提供各种用于应用层数据的编码和转换功能,确保一个系统的应用层发送的数据能被另一个系统的应用层识别。如果必要,该层可提供一种标准表示形式,用于将计算机内部的多种数据格式转换成通信中采用的标准表示形式。数据压缩和加密也是表示层可提供的转换功能之一。(转化,解压,加密等)
会话层
会话层就是负责建立、管理和终止表示层实体之间的通信会话。该层的通信由不同设备中的应用程序之间的服务请求和响应组成.(服务间的对接)
传输层
传输层建立了主机端到端的链接,传输层的作用是为上层协议提供端到端的可靠和透明的数据传输服务,包括处理差错控制和流量控制等问题。TCP UDP就是在这一层
网络层
本层通过IP寻址来建立两个节点之间的连接,为源端的运输层送来的分组,选择合适的路由和交换节点,正确无误地按照地址传送给目的端的运输层。就是通常说的IP层。这一层就是我们经常说的IP协议层。IP协议是Internet的基础。
数据链路层
将比特组合成字节,再将字节组合成帧,使用链路层地址 (以太网使用MAC地址)来访问介质,并进行差错检测。
物理层
实际最终信号的传输是通过物理层实现的。通过物理介质传输比特流。规定了电平、速度和电缆针脚。常用设备有(各种物理设备)集线器、中继器、调制解调器、网线、双绞线、同轴电缆。这些都是物理层的传输介质。
TCP四层网络模型
三次握手\四次挥手
三次握手
TCP位于传输层,作用是提供可靠的字节流服务,为了准确无误地将数据送达目的地,TCP协议采纳三次握手策略。
原理
- 发送端首先发送一个带有SYN(synchronize)标志地数据包给接收方。
- 接收方接收后,回传一个带有SYN/ACK标志的数据包传递确认信息,表示我收到了。
- 最后,发送方再回传一个带有ACK标志的数据包,代表我知道了,表示’握手‘结束。
通俗的说法
- Client:嘿,李四,是我,听到了吗?
- Server:我听到了,你能听到我的吗?
- Client:好的,我们互相都能听到对方的话,我们的通信可以开始了。
四次挥手
- 第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。
- 第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。
- 第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。
- 第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手
通俗的说法
1)Client:我所有东西都说完了
2)Server:我已经全部听到了,但是等等我,我还没说完
3)Server:好了,我已经说完了
4)Client:好的,那我们的通信结束l
通讯协议
网络层协议
IP
传输层协议
TCP
UDP
会话层协议
- HTTP---超文本传输协议(Hyper Text Transfer Protocol,HTTP)
- HTTP协议工作于客户端-服务端架构上。浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。Web服务器根据接收到的请求后,向客户端发送响应信息。
- HTTP默认端口号为80,但是你也可以改为8080或者其他端口。
- HTTP三点注意事项:
- HTTP是无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
- HTTP是媒体独立的:这意味着,只要客户端和服务器知道如何处理的数据内容,任何类型的数据都可以通过HTTP发送。
- HTTP是无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
HTTP的缺点
HTTP虽然使用极为广泛, 但是却存在不小的安全缺陷, 主要是其数据的明文传送和消息完整性检测的缺乏, 而这两点恰好是网络支付, 网络交易等新兴应用中安全方面最需要关注的
- HTTPS---(全称:Hyper Text Transfer Protocol over SecureSocket Layer)超文本传输安全协议
是以安全为目标的 HTTP 通道,在HTTP的基础上通过传输加密和身份认证保证了传输过程的安全性
- FTP
文件传输协议(File Transfer Protocol,FTP)是用于在网络上进行文件传输的一套标准协议
- SMTP
SMTP是一种提供可靠且有效的电子邮件传输的协议。SMTP是建立在FTP文件传输服务上的一种邮件服务,主要用于系统之间的邮件信息传递,并提供有关来信的通知。
Socket编程
TCP
TCP(Transmission Control Protocol),即传输控制协议。是一种面向连接的、可靠的、基于字节流的传输层通信协议
服务端:
1 package com.hhr; 2 3 4 import java.io.InputStream; 5 import java.io.OutputStream; 6 import java.net.InetAddress; 7 import java.net.ServerSocket; 8 import java.net.Socket; 9 import java.net.UnknownHostException; 10 11 public class EasyTCP { 12 public static final String SERVICE_IP = "127.0.0.1"; 13 14 public static final int SERVICE_PORT = 10101; 15 16 public static final char END_CHAR = '#'; 17 //服务端最大连接数 18 public static final int MAX_COUNT=10; 19 20 public static void main(String[] args) { 21 EasyTCP service = new EasyTCP(); 22 // 启动服务端 23 service.startService(SERVICE_IP, SERVICE_PORT); 24 } 25 26 private void startService(String serverIP, int serverPort) { 27 try { 28 // 封装服务端地址 29 InetAddress serverAddress = InetAddress.getByName(serverIP); 30 // 建立服务端 31 try (ServerSocket service = new ServerSocket(serverPort, 10, serverAddress)) { 32 while (true) { 33 StringBuilder receiveMsg = new StringBuilder(); 34 // 接受一个连接,该方法会阻塞程序,直到一个链接到来 35 try (Socket connect = service.accept()) { 36 // 获得输入流 37 InputStream in = connect.getInputStream(); 38 39 // 解析输入流,遇到终止符结束,该输入流来自客户端 40 for (int c = in.read(); c != END_CHAR; c = in.read()) { 41 if (c == -1) 42 break; 43 receiveMsg.append((char) c); 44 } 45 46 // 组建响应信息 47 String response = "Hello world " + receiveMsg.toString() + END_CHAR; 48 49 // 获取输入流,并通过向输出流写数据的方式发送响应 50 OutputStream out = connect.getOutputStream(); 51 out.write(response.getBytes()); 52 } catch (Exception e) { 53 e.printStackTrace(); 54 } 55 } 56 } catch (Exception e) { 57 e.printStackTrace(); 58 } 59 } catch (UnknownHostException e) { 60 e.printStackTrace(); 61 } 62 } 63 }
客户端
1 package com.hhr; 2 3 import java.io.InputStream; 4 import java.io.OutputStream; 5 import java.net.Socket; 6 import java.text.SimpleDateFormat; 7 import java.util.Date; 8 import java.util.Scanner; 9 10 public class TCPClient { 11 12 public static void main(String[] args) { 13 14 TCPClient client = new TCPClient(); 15 16 SimpleDateFormat format = new SimpleDateFormat("hh-MM-ss"); 17 18 Scanner scanner = new Scanner(System.in); 19 20 while(true){ 21 22 String msg = scanner.nextLine(); 23 24 if("#".equals(msg)) 25 26 break; 27 28 //打印响应的数据 29 30 System.out.println("send time : " + format.format(new Date())); 31 32 System.out.println(client.sendAndReceive(EasyTCP.SERVICE_IP,EasyTCP.SERVICE_PORT,msg)); 33 34 System.out.println("receive time : " + format.format(new Date())); 35 36 } 37 38 } 39 40 private String sendAndReceive(String ip, int port, String msg){ 41 42 //这里比较重要,需要给请求信息添加终止符,否则服务端会在解析数据时,一直等待 43 44 msg = msg+EasyTCP.END_CHAR; 45 46 StringBuilder receiveMsg = new StringBuilder(); 47 48 //开启一个链接,需要指定地址和端口 49 50 try (Socket client = new Socket(ip, port)){ 51 52 //向输出流中写入数据,传向服务端 53 54 OutputStream out = client.getOutputStream(); 55 56 out.write(msg.getBytes()); 57 58 //从输入流中解析数据,输入流来自服务端的响应 59 60 InputStream in = client.getInputStream(); 61 62 for (int c = in.read(); c != EasyTCP.END_CHAR; c = in.read()) { 63 64 if(c==-1) 65 66 break; 67 68 receiveMsg.append((char)c); 69 70 } 71 72 }catch (Exception e){ 73 74 e.printStackTrace(); 75 76 } 77 78 return receiveMsg.toString(); 79 80 } 81 82 }
UDP
服务器
1 public static void main(String[] args) throws IOException { 2 //创建数据包对象,封装要发送的数据,接受端IP,端口 3 byte[] data="你好UDP".getBytes(); 4 //创建InetAddress对象,封装自己的IP地址 5 InetAddress inet=InetAddress.getByName("127.0.0.1"); 6 DatagramPacket dp=new DatagramPacket(data,data.length,inet,6000); 7 //创建DatagramSocket对象,数据包的发送和接受对象 8 DatagramSocket ds=new DatagramSocket(); 9 //调用ds对象的方法send,发送数据包 10 ds.send(dp); 11 ds.close(); 12 }
客户端
1 public static void main(String[] args) throws IOException { 2 //创建数据包传输对象DatagramSocket 绑定端口号 3 DatagramSocket ds=new DatagramSocket(6000); 4 //创建字节数组 5 byte[] data=new byte[1024]; 6 //创建数据包对象,传递字节数组 7 DatagramPacket dp=new DatagramPacket(data, data.length); 8 //调用ds对象的方法receive传递数据包 9 ds.receive(dp); 10 //获取发送端的IP地址对象 11 String ip=dp.getAddress().getHostAddress(); 12 //获取发送的端口号 13 int port=dp.getPort(); 14 //获取接收到的字节数 15 int length=dp.getLength(); 16 System.out.println(new String(data,0,length)+"...."+ip+":"+port); 17 ds.close(); 18 }