当前位置: 首页 > news >正文

网络传输过程网络编程

网络名词解释

1、局域网(LAN)和广域网(WAN):
局域网是覆盖范围最小的网络;而广域网就是“连接不同的局域网”。二者没有严格的界限。
2、交换机和路由器:
交换机的核心作用是在局域网(如家庭 WiFi、公司内网)内部,实现多台设备的高速连接和数据交换;而路由器的核心作用是连接两个或多个不同的网络(如家庭局域网和互联网),并确定数据传输的最佳路径。
3、IP地址和端口号:
IP 地址是分配给网络中设备(如电脑、手机、服务器)的唯一标识,用于区分是哪个机器设备;对于一个机器设备上可能运行着多个网络服务(如浏览器访问网页、微信聊天、下载文件),端口号就是用于区分同一设备上的不同服务。
4、协议:
本质是设备间 “对话” 的统一规则手册,为了让不同系统、不同类型的设备之间传递的信息都彼此理解。

协议分层

对于网络通信是很复杂的,需要对协议进行分成,上层协议调用下层协议,下层协议为上层协议提供服务。每一层只负责特定任务并为上层提供服务,无需关心其他层的具体细节,体现封装的特性。对于每一层具体使用的协议也可以灵活替换,体现解耦合的特性。
对于协议分层有两种模型:OSI七层网络模型、TCP/IP五层网络模型
OSI七层网络模型(从上层到下层):应用层、表示层、会话层、传输层、网络层、数据链路层、物理层。这样模型十分复杂不实用,及对其进行简化也就有了TCP/IP五层网络模型

TCP/IP五层网络模型

每一层都呼叫它的下一层所提供的网络来完成自己的需求。
应用层 -> 传输层 -> 网络层 -> 数据链路层 -> 物理层

TCP/IP五层网络模型核心功能对应OSI七层网络模型常见协议/设备
应用层使用数据和构造传输数据应用层、表示层、会话层HTTP/HTTPS、DNS
传输层两台主机之间的数据传输。解决 “数据如何高效、可靠地从源应用传输到目标应用” 的问题传输层TCP协议、UDP协议
网络层负责跨网络的路由选择和数据包转发,通过 IP 地址确定传输路径,实现不同网络间的通信。数据从起点到终点的中间路径怎么走的网络层IP协议
数据链路层两个相邻节点之间的具体传输过程数据链路层以太网协议、交换机
物理层负责硬件间的原始信号传输物理层网线、光纤

TCP/IP五层网络模型中的五元组

1、源IP:标识源主机
2、源端口号:标识源主机中哪个进程发送的数据
3、目的IP:表示目的主机
4、目的端口号:标识目的主机中哪个进程接收数据
5、协议号:用于标识上层协议类型的数字标识,主要作用是让接收方设备明确 “当前数据包的上层应该交给哪个协议处理”。(协议类型)

传输大致过程

网络数据传输的流程:封装和分用
在这里插入图片描述

Socket:套接字

Socket也就是传输层给应用层提供的编程接口。
主要为两类:流套接字、数据报套接字。
对于TCP协议来说:特点为有连接、可靠传输、面向字节流、全双工;
对于UDP协议来说:特点为无连接、不可靠传输、面向数据报、全双工。
也就是说“流套接字”提供给TCP协议使用的,“数据报套接字”提供给UDP协议使用的。

特点说明
有连接在正式通信之前需要让通信双方保存对方的关键信息(IP和端口号),在通信结束之后,再删除对方的关键信息
无连接直接发送数据
可靠传输尽可能地把数据报传输给对方,就算不能确保数据报到达,也知道接收方是否收到了数据报
不可靠传输不考虑是否丢包
面向字节流与按字节为方式地读写文件类似,一次读多少个字节都可以
面向数据报每次读写都要以一个UDP数据报为单位
全双工一个通信,可以进行双向传输
半双工一个通信只能单向传输

数据报套接字

核心两个类:DatagramPacketDatagramSocket
DatagramSocket:表示socket文件。
DatagramPacket:表示数据报。

实现回显功能

代码展示

UDP服务器:

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;public class UdpEchoServer {private DatagramSocket socket = null;public UdpEchoServer(int port) throws SocketException {this.socket = new DatagramSocket(port);}//启动服务器public void start() throws IOException {System.out.println("server start!");while (true){//1、读取请求并解析DatagramPacket requestPacket = new DatagramPacket(new byte[1024],1024);socket.receive(requestPacket);//receive收到的数据是二进制数据,而我们需要的是字符串,需要进行转换String request = new String(requestPacket.getData(),0,requestPacket.getLength());//2、根据请求计算响应String response = process(request);//3、把响应返回给客户端,DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),response.getBytes().length,requestPacket.getSocketAddress());//需要再次构造一个DatagramPacketsocket.send(responsePacket);//4、打印日志System.out.printf("[%s : %d],request: %s,response: %s\n",requestPacket.getAddress().toString(),requestPacket.getPort(),request,response);}}private String process(String request){//表示 根据请求 计算 响应 的方法return request;}public static void main(String[] args) throws IOException {UdpEchoServer server = new UdpEchoServer(6060);server.start();}
}

UDP客户端:

import java.io.IOException;
import java.net.*;
import java.util.Scanner;public class UdpEchoClient {private DatagramSocket socket = null;private String serverIP;private int serverPort;public UdpEchoClient(String serverIP ,int serverPort) throws SocketException {//传入服务器IP和服务器端口this.socket = new DatagramSocket();this.serverIP = serverIP;this.serverPort = serverPort;}public void start() throws IOException {System.out.println("client start!");Scanner scanner = new Scanner(System.in);while (true){//1、用户从控制台输入System.out.print("请输入-> ");String request = scanner.next();if(request.equals("exit")){break;}//2、把用户输入的字符串构造成UDP数据报,发送给服务器DatagramPacket requestPacket = new DatagramPacket(request.getBytes(),request.getBytes().length,InetAddress.getByName(this.serverIP),this.serverPort);socket.send(requestPacket);//3、从服务器读取响应DatagramPacket responsePacket = new DatagramPacket(new byte[1024],1024);socket.receive(responsePacket);String response = new String(responsePacket.getData(),0,responsePacket.getLength());//4、显示响应System.out.println(response);}}public static void main(String[] args) throws IOException {UdpEchoClient client = new UdpEchoClient("127.0.0.1",6060);client.start();}
}
代码运行流程及解释

在这里插入图片描述
需要注意的是:
1、客户端不能指定端口号! 客户端程序运行在用户设备上,程序员并不知道用户设备上有哪些进程占用了哪些端口,此时就不能指定一个端口。当没有指定客户端端口时,操作系统会自动分配出一个空闲的端口号
服务器是由程序员控制的,可以保证端口号不会冲突。
2、在客户端程序的构造方法中传入服务器的IP和端口号,这样在客户端发送请求的时候就知道了“五元组”;在服务器返回响应的时候通过构造数据报传入客户端的IP和端口号,就知道了“五元组”。有了“五元组”客户端和服务器之间就可以进行通信了。
3、对于socket来说也是文件,用完之后需要关闭(调用close()方法),否则可能导致文件资源泄露的问题。但对于这个程序的socket来说,应该要一直使用,直到进程结束(生命周期随整个进程结束而结束)。进程结束,PCB释放了,里面的文件描述符表也释放了,也就不必担心“泄露”的问题了。

实现一部英译汉字典的功能

对于客户端来说,发送的是字符串,返回结果也是字符串,可以直接复用UdpEchoClient回显客户端;对于服务器来说,大部分是一样的,只需要修改“根据请求计算响应”的部分即可,这时候采用继承的方式。

import java.io.IOException;
import java.net.SocketException;
import java.util.HashMap;public class UdpDicServer extends UdpEchoServer{private HashMap<String,String> dic = new HashMap<>();public UdpDicServer(int port) throws SocketException {super(port);//构造出一部字典来dic.put("hello","你好");dic.put("world","世界");dic.put("client","客户");dic.put("server","服务");dic.put("red","红色");dic.put("read","读");}@Overridepublic String process(String request){return dic.getOrDefault(request, "没有找到该单词");}public static void main(String[] args) throws IOException {UdpDicServer server = new UdpDicServer(6060);server.start();}
}

由于需要重写process()方法,而原本UdpEchoServer 中的 process() 方法是私有的,不能被重写,需要将其修改为公有的。

流套接字

TCP传输的基本单位是字节。
核心两个类:SocketServerSocket
ServerSocket:负责把连接到服务器的客户端进行统一处理。
Socket:针对一个客户端提供具体的服务(读写数据)。

实现回显功能

代码展示

TCP服务器:

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;public class TcpEchoServer {private ServerSocket serverSocket = null;public TcpEchoServer(int port) throws IOException {this.serverSocket = new ServerSocket(port);}public void start() throws IOException {System.out.println("server start!");while (true){//1、首先接收客户端的连接,才能进行通信Socket socket = serverSocket.accept();//2、通过下面的方法来处理 整个连接过程processConnection(socket);}}private void processConnection(Socket socket) throws IOException {System.out.printf("[%s:%d] 客户端上线!\n", socket.getInetAddress(), socket.getPort());try (InputStream inputStream = socket.getInputStream();OutputStream outputStream = socket.getOutputStream()){Scanner scanner = new Scanner(inputStream);PrintWriter printWriter = new PrintWriter(outputStream);while (true){//处理多次请求//1、读取数据if(!scanner.hasNext()){System.out.printf("[%s ,%d]客户端下线\n",socket.getInetAddress().toString(),socket.getPort());break;}String request = scanner.next();//2、根据请求计算响应String response = process(request);//3、把请求返回给客户端printWriter.println(response);printWriter.flush();//冲刷缓冲区//4、打印日志System.out.printf("[%s ,%d], request: %s, response: %s\n",socket.getInetAddress().toString(),socket.getPort(),request,response);}}catch (IOException e){e.printStackTrace();}finally {socket.close();//关闭socket文件}}public String process(String request){return request;}public static void main(String[] args) throws IOException {TcpEchoServer tcpEchoServer = new TcpEchoServer(9090);tcpEchoServer.start();}
}

TCP客户端:

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;public class TcpEchoClient {private Socket socket = null;public TcpEchoClient(String serverIP,int serverPort) throws IOException {socket = new Socket(serverIP,serverPort);}public void start(){System.out.println("client start!");Scanner scanner = new Scanner(System.in);try(InputStream inputStream = socket.getInputStream();OutputStream outputStream = socket.getOutputStream()){Scanner scannerNetwork = new Scanner(inputStream);PrintWriter printWriter = new PrintWriter(outputStream);while (true){//1、用户从控制台输入System.out.print("请输入-> ");String request = scanner.next();if(request.equals("exit")){break;}//2、把用户输入的字符串发送给服务器printWriter.println(request);printWriter.flush();//冲刷缓冲区//3、从服务器读取响应if(!scannerNetwork.hasNext()){break;}String response = scannerNetwork.next();//4、显示响应System.out.println(response);}}catch (IOException e){e.printStackTrace();}}public static void main(String[] args) throws IOException {TcpEchoClient tcpEchoClient = new TcpEchoClient("127.0.0.1",9090);tcpEchoClient.start();}
}
代码解释

1、在客户端程序中,调用构造方法创建Socket对象时,就会触发TCP建立连接的过程。但服务器需要将建立好的连接告诉应用程序。
2、在PrintWriter类中设置了缓冲区,把要写入IO设备的数据,先放入缓冲区中,等缓冲区差不多满的时候,再统一写入IO设备中。这就会导致服务器无法及时的做出响应。需要调用flush()方法,将缓冲区的数据写入IO设备中去。
3、对于文件关闭,UDP中socket对象是跟随整个进程的,TCP客户端中的socket对象也是跟随整个客户端进程的,TCP服务器中的serverSocket对象也是跟随整个服务器进程的,而TCP服务器中的socket对象只是针对某个客户端的,当客户端结束时需要去释放socket文件。(每次有客户端连接上服务器,都会触发一次accept,都会创建一个socket对象)
4、对于上述代码中,都需要以\n为结束读取标志,这样就知道一次请求中要传输多少字节。
5、一个服务器是要给多个客户端提供服务的,而上述代码中当一个客户端accept进行连接之后,进入processConnection()方法中的while循环,当其他客户端建立连接(服务器并没有执行accept操作),其他客户端连接没有获取到应用程序中。此时可以将服务器设计成多线程,服务器就可以接收到其他客户端连接了。

public void start() throws IOException {System.out.println("server start!");while (true){//1、首先接收客户端的连接,才能进行通信Socket socket = serverSocket.accept();//2、通过下面的方法来处理 整个连接过程Thread thread = new Thread(() -> {try {processConnection(socket);} catch (IOException e) {throw new RuntimeException(e);}});thread.start();}
}

也可以设计成线程池

public void start() throws IOException {System.out.println("server start!");ExecutorService executorService = Executors.newCachedThreadPool();while (true){//1、首先接收客户端的连接,才能进行通信Socket socket = serverSocket.accept();//2、通过下面的方法来处理 整个连接过程executorService.submit(() ->{try {processConnection(socket);} catch (IOException e) {throw new RuntimeException(e);}});}
}

实现一部英译汉字典的功能

import java.io.IOException;
import java.util.HashMap;public class TcpDicServer extends TcpEchoServer{private HashMap<String,String> dic = new HashMap<>();public TcpDicServer(int port) throws IOException {super(port);dic.put("hello","你好");dic.put("world","世界");dic.put("client","客户");dic.put("server","服务");dic.put("red","红色");dic.put("read","读");}@Overridepublic String process(String request){return dic.getOrDefault(request, "没有找到该单词");}public static void main(String[] args) throws IOException {TcpDicServer tcpDicServer = new TcpDicServer(9090);tcpDicServer.start();}
}

和UDP的思路一样,使用继承,复用代码。

http://www.dtcms.com/a/532726.html

相关文章:

  • 做指甲的网站广州天河区怎么样
  • 做网站买什么服务器吗域名空间结构
  • 做电影网站算侵权吗进出口贸易公司取名大全
  • 深度学习中的正则化(Regularization)详解
  • 数据库的安全与保护
  • 网站不同wordpress加分页
  • FFmpeg 基本数据结构 AVCodecContext分析
  • (全闭环)FUNC_FullCloseLoop
  • 出口外贸网站建设铜川网站建设哪家好
  • Gorm(五)钩子实践
  • 我怎么才能找到免费的VR场景以及用于虚拟人的舞蹈动作?
  • 九江企业网站制作苏州园区建设网站首页
  • 怎么将很多ppt批量转换成pptx?图文操作指南
  • 阜宁做网站哪家公司最好wordpress仿论坛主题
  • Perplexity Comet: AI 浏览器免费使用GPT5、Claude4、Gemini2.5Pro
  • Git的原理与使用 -- 基础操作
  • python自动化004:api(接口)最基础的框架
  • 家具行业网站整站模板网站开发公司方案
  • wordpress网站多语言南昌关键词优化平台
  • c#接口请求报错
  • Linux小课堂: 网络接口与连接监控命令详解
  • 做网站九州科技汕头网站建设浩森宇特
  • GitHub等平台形成的开源文化正在重塑可以调
  • 流批了,pdf批量转excel
  • GitHub等平台形成的开源文化正在重塑家庭日快
  • 怎么在搜索引擎做网站登记metropro wordpress
  • Appium 手机自动化控制教程
  • 节流(throttle) 是一种优化高频触发事件的技术
  • 免费空间域名可以做淘宝客网站推广吗优秀网站开发公司
  • 决策树(ID3、C4.5与CART)——从信息增益、信息增益率到基尼系数