网络编程(TCP、UDP)
文章目录
- 一、概念
- 1.1 什么是网络编程
- 1.2 网络编程中的基本知识
- 二、Socket套接字
- 2.1 概念及分类
- 2.2 TCP VS UDP
- 2.3 通信模型
- 2.4 接口方法
- UDP数据报套接字编程
- TCP流套接字编程
- 三、代码示例
- 3.1 注意点
- 3.2 回显服务器
- 基于UDP
- 基于TCP
一、概念
首先介绍了什么是网络编程,随后介绍了接收端发送端、请求响应等基本知识
1.1 什么是网络编程
网络编程:
(1)网络上的主机,通过不同的进程,以编程的方式实现网络通信(或称为网络数据传输)。(2)在程序员层面上,即要写一个应用程序通过调用传输层提供的API实现网络通信
1.2 网络编程中的基本知识
-
发送端和接收端:字面意思,发送端是发送数据的,接收端是接收数据的,注意这个概念只是相对的,主要看数据是从哪发到哪。
-
请求和响应:
一般来说,获取一个网络资源,涉及到两次网络数据传输:- 第一次:请求数据的发送
- 第二次:响应数据的发送
-
客户端和服务器
服务端:在常见的网络数据传输场景下,给用户提供服务的一方进程
客户端:获取服务的一方进程,是指给用户使用的程序 -
常见的客户端服务端模型
- 客户端先发送请求到服务端
- 服务端根据请求数据,执行相应的业务处理
- 服务端返回响应:发送业务处理结果
- 客户端根据响应数据,展示处理结果(展示获取的资源,或提示保存资源的处理结果)
二、Socket套接字
网络编程是基于Socket开发的,传输层上主要涉及TCP、UDP这两种协议,而他俩给出的API都不同,本段主要介绍概念,包括分类和区别。
2.1 概念及分类
(1)Socket套接字,是由系统提供用于网络通信的技术,是基于TCP/IP协议的网络通信的基本操作单元。基于Socket套接字的网络程序开发就是网络编程。
(2)Socket套接字主要针对传输层协议划分为如下三类:
- 流套接字:传输层TCP协议(传输控制协议)
- 数据报套接字:传输层UDP协议(用户数据报协议)
- 原始套接字:原始套接字用于自定义传输层协议,用于读写内核没有处理的IP协议数据
2.2 TCP VS UDP
TCP:有连接;可靠传输;面向字节流;有接收缓冲区和发送缓冲区;大小不限;全双工
UDP:无连接;不可靠传输;面向数据报;有接收缓冲区,无发送缓冲区;大小受限,一次最多传输64k
- 连接:客户端和服务器之间是否使用内存保存对端信息,互相承认,连接就建立了。
- 传输:
- 可靠传输:A尽可能把消息传过去,传输失败与否都能感知到,会降低传输效率。不可靠传输传输效率更高
- 注意:这并不意味着,TCP比UDP更安全,因为“网络安全”指的是传输的数据是否容易被黑客截获,以及如果被截获后是否会泄漏一些重要信息
- 字节流VS数据报:
- 面向字节流:TCP流式操作
- 面向数据报:读写的基本单位是一个UDP数据报,且一次只能传输一个
- 全双工VS半双工
- 全双工:一个通道,可以双向通信。网线就是全双工的
- 半双工:一个通道,只能单向通信
2.3 通信模型
数据报套接字模型:
流套接字模型:
2.4 接口方法
UDP数据报套接字编程
UDP提供的API主要通过两个类来实现,一个是DatagramSocket,一个是DatagramPacket。
DatagramSocket 方法:代表一个Socket对象,即一个网卡的文件
DatagramPacket 方法:代表一个UDP数据报
TCP流套接字编程
因为TCP是字节流式传输,所以不需要一个专门的类来表示TCP数据报
ServerSocket 方法:
(1)给服务器使用的
(2)负责拉客,在外场广撒网。
Socket 方法:
(1)服务端和客户端都能用
(2)像是一个耳麦,可以直接与对方进行通信,负责在内场细致服务。
三、代码示例
3.1 注意点
- 服务器使用的端口需要手动指定,客户端的则需要系统自动分配
- 因为服务器需要能被客户端百分百找到,万一服务器随便改变端口,那客户端按照以往的连接是无法连接到服务器的。
- 客户端则没有这个需求,且客户端一旦指定端口号很可能回合其他程序冲突,系统自动分配的端口号一定是空闲的。
- flush() ------ 手动刷新
- IO操作是比较有开销的,相比于访问内存,进行IO次数越多,程序的速度就越慢。为了解决这个问题,我们会使用一块内存作为缓冲区,写数据的时候,先写到缓冲区里。攒了一波数据之后,统一进行IO。
- printWriter 内置了缓冲区
- flush()可以实现手动刷新,可以确保这里的数据是真的通过网卡发出去了,而不是残留在内存缓冲区中的
- 加上flush()可以让代码更稳妥,但是不加不一定会出错,因为缓冲区内置了一定的刷新策略
- 关于 close()
close() 主要是删除文件描述符表中的记录。当然也并不是每个流对象都有文件描述符表,只有那种调用了操作系统提供的open()方法,涉及到了用户态和用户态。
3.2 回显服务器
基于UDP
(1)InetAddress 表示的是IP地址
(2)客户端要设置要传给的服务器的IP地址和端口号是多少,即示例中的 serverIp 和 serverPort 。服务器则是要手动指定一个端口号。
(3)难点在于 DatagramPacket 的构造,涉及了String 和 DatagramPacket 之间的转换。
(4)数据包的接收和发送,依靠 DatagramSocket 的 send 和 receive 方法。
//客户端
public class UdpEchoClient {private DatagramSocket socket = null;private String serverIp;private int serverPort;public UdpEchoClient(String ip, int port) throws SocketException {serverIp = ip;serverPort = port;socket = new DatagramSocket();}public void start() throws IOException {//获取用户输入的内容Scanner scanner = new Scanner(System.in);System.out.println("客户端启动!");//给服务器发送响应while (true){System.out.print("-> ");String request = scanner.next();//不能用request.length(),因为这是指字符长度,我们需要的是字节长度//除非是纯英文且由utf-8编码,那么两者会相同。Socket是按照字节来处理的。DatagramPacket requestPacket = new DatagramPacket(request.getBytes(), request.getBytes().length,InetAddress.getByName(serverIp), serverPort);socket.send(requestPacket);//接收响应DatagramPacket responsePacket = new DatagramPacket(new byte[4096], 4096);socket.receive(responsePacket);String response = new String(responsePacket.getData(), 0, responsePacket.getLength());System.out.println(response);}}public static void main(String[] args) throws IOException {UdpEchoClient client = new UdpEchoClient("127.0.0.1", 9090);client.start();}
}
//服务器
public class UdpEchoServer {private DatagramSocket socket = null;public UdpEchoServer(int port) throws SocketException {socket = new DatagramSocket(port);}public void start() throws IOException {System.out.println("服务器启动");while(true){DatagramPacket requestPacket = new DatagramPacket(new byte[4096], 4096);socket.receive(requestPacket);String request = new String(requestPacket.getData(), 0, requestPacket.getLength());String response = process(request);DatagramPacket responsePacket = new DatagramPacket(response.getBytes(), response.getBytes().length,requestPacket.getSocketAddress());socket.send(responsePacket);System.out.printf("[%s:%d req:%s, resp:%s\n]", requestPacket.getAddress().toString(),requestPacket.getPort(), request, response);}}public String process(String request){return request;}public static void main(String[] args) throws IOException {UdpEchoServer server= new UdpEchoServer(9090);server.start();}
}
基于TCP
- 服务器对客户是多对多的关系,一个服务器内核会存许多客户端的连接(建立连接的过程,系统内核会自己完成)。连接就像是一个个代办事项,等待应用程序一个个完成。
- serverSocket.accept():将在内核中已经建立好的连接取出来给应用程序
- 原理是一个【生产者消费者模型】
- TCP中的长短连接
- 短连接:每次接收到数据并返回响应后,都关闭连接,即只能一次收发数据
- 长连接:不关闭连接,一直保持连接状态,双方不停的收发数据
public class TcpServer {private ServerSocket socket = null;private ExecutorService service = Executors.newCachedThreadPool();public TcpServer(int port) throws IOException {socket = new ServerSocket(9090);}public void start() throws IOException {System.out.println("服务端启动!");while (true){Socket clientSocket = socket.accept();//为了能够接收多个客户端,这里使用了线程池//当客户端进一步增加,线程数目也会增加,系统的负担也就越来越重,响应速度也就越来越慢//为了解决这个问题,就需要开源(引入更多的硬件资源)节流(减少每种硬件资源占用的资源)service.submit(new Runnable() {@Overridepublic void run() {try {processConnection(clientSocket);} catch (IOException e) {throw new RuntimeException(e);}}});}}public void processConnection(Socket clientSocket) throws IOException {try(InputStream inputStream = clientSocket.getInputStream();OutputStream outputStream = clientSocket.getOutputStream()){while(true){Scanner scannerClient = new Scanner(inputStream);String request = scannerClient.next();String response = process(request);PrintWriter writer = new PrintWriter(outputStream);writer.println(response);writer.flush();System.out.printf("[%s:%d] req:%s, resp:%s\n", clientSocket.getInetAddress().toString(),clientSocket.getPort(), request, response);}} catch (IOException e) {throw new RuntimeException(e);}finally {clientSocket.close();}}public String process(String request){return request;}public static void main(String[] args) throws IOException {TcpServer server = new TcpServer(9090);server.start();}
}
public class TcpClient {private Socket socket = null;public TcpClient(String serverIp, int serverPort) throws IOException {socket = new Socket(serverIp, serverPort);}public void start(){System.out.println("客户端启动");Scanner scanner = new Scanner(System.in);try(InputStream inputStream = socket.getInputStream();OutputStream outputStream = socket.getOutputStream()){while (true){System.out.print("---->");String request = scanner.next();PrintWriter writer = new PrintWriter(outputStream);writer.println(request);writer.flush();Scanner scammerConsole = new Scanner(inputStream);String response = scammerConsole.next();System.out.println(response);}} catch (IOException e) {throw new RuntimeException(e);}}public static void main(String[] args) throws IOException {TcpClient client = new TcpClient("127.0.0.1", 9090);client.start();}
}
相关文章:

网络编程(TCP、UDP)
文章目录 一、概念1.1 什么是网络编程1.2 网络编程中的基本知识 二、Socket套接字2.1 概念及分类2.2 TCP VS UDP2.3 通信模型2.4 接口方法UDP数据报套接字编程TCP流套接字编程 三、代码示例3.1 注意点3.2 回显服务器基于UDP基于TCP 一、概念 首先介绍了什么是网络编程ÿ…...

Python快速入门系列-7(Python Web开发与框架介绍)
第七章:Python Web开发与框架介绍 7.1 Flask与Django简介7.1.1 Flask框架Flask的特点Flask的安装一个简单的Flask应用示例7.1.2 Django框架Django的特点Django的安装一个简单的Django应用示例7.2 前后端交互与数据传输7.2.1 前后端交互7.2.2 数据传输格式7.2.3 示例:使用Flas…...
最长对称子串
对给定的字符串,本题要求你输出最长对称子串的长度。例如,给定Is PAT&TAP symmetric?,最长对称子串为s PAT&TAP s,于是你应该输出11。 输入格式: 输入在一行中给出长度不超过1000的非空字符串。 输出格式&…...

【大模型】大模型 CPU 推理之 llama.cpp
【大模型】大模型 CPU 推理之 llama.cpp llama.cpp安装llama.cppMemory/Disk RequirementsQuantization测试推理下载模型测试 参考 llama.cpp 描述 The main goal of llama.cpp is to enable LLM inference with minimal setup and state-of-the-art performance on a wide var…...

异地组网怎么管理?
在当今信息化时代,随着企业的业务扩张和员工的分布,异地组网已经成为越来越多企业的需求。异地组网管理相对来说是一项复杂而繁琐的任务。本文将介绍一种名为【天联】的管理解决方案,帮助企业更好地管理异地组网。 【天联】组网的优势 【天联…...

Kafka参数介绍
官网参数介绍:Apache KafkaApache Kafka: A Distributed Streaming Platform.https://kafka.apache.org/documentation/#configuration...

如何利用待办事项清单提高工作效率?
你是否经常因为繁重的工作量而感到不堪重负?你是否在努力赶工期或经常忘记重要的电子邮件?你并不是特例。如何利用待办事项清单提高工作效率?这里有一个简单的方法可以帮你理清混乱并更高效地完成任务—待办事项清单。 这种类型的清单可以帮…...
力扣经典150题第二题:移除元素
移除元素问题详解与解决方法 1. 介绍 移除元素问题是 LeetCode 经典题目之一,要求原地修改输入数组,移除所有数值等于给定值的元素,并返回新数组的长度。 问题描述 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等…...

55555555555555
欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起学习和分享Linux、C、C、Python、Matlab,机器人运动控制、多机器人协作,智能优化算法,滤波估计、多传感器信息融合,机器学习,人工智能等相关领域的知识和…...
用Skimage学习数字图像处理(018):图像形态学处理(上)
本节开始讨论图像形态学处理,这是上篇,将介绍与二值形态学相关的内容,重点介绍两种基本的二值形态学操作:腐蚀和膨胀,以及三种复合二值形态学操作:开、闭和击中击不中变换。 目录 9.1 基础 9.2 基本操作…...
MySQL中 in 和 exists 区别
在MySQL中,IN和EXISTS都是用于在子查询中测试条件的操作符,但它们在处理和效率上有一些重要的区别。MySQL中的in语句是把外表和内表作hash连接,⽽exists语句是对外表作loop循环,每次loop循环再对内表进⾏查询。⼤家⼀直认为exists…...

Java基础 - 代码练习
第一题:集合的运用(幸存者) public class demo1 {public static void main(String[] args) {ArrayList<Integer> array new ArrayList<>(); //一百个囚犯存放在array集合中Random r new Random();for (int i 0; i < 100; …...

【Redis】redis集群模式
概述 Redis集群,即Redis Cluster,是Redis 3.0开始引入的分布式存储方案。实际使用中集群一般由多个节点(Node)组成,Redis的数据分布在这些节点中。集群中的节点分为主节点和从节点:只有主节点负责读写请求和集群信息的维护&#…...

基于opencv的猫脸识别模型
opencv介绍 OpenCV的全称是Open Source Computer Vision Library,是一个跨平台的计算机视觉库。OpenCV是由英特尔公司发起并参与开发,以BSD许可证授权发行,可以在商业和研究领域中免费使用。OpenCV可用于开发实时的图像处理、计算机视觉以及…...

基于注意力整合的超声图像分割信息在乳腺肿瘤分类中的应用
基于注意力整合的超声图像分割信息在乳腺肿瘤分类中的应用 摘要引言方法 Segmentation information with attention integration for classification of breast tumor in ultrasound image 摘要 乳腺癌是世界范围内女性最常见的癌症之一。基于超声成像的计算机辅助诊断&#x…...

数据库重点知识(个人整理笔记)
目录 1. 索引是什么? 1.1. 索引的基本原理 2. 索引有哪些优缺点? 3. MySQL有哪几种索引类型? 4. mysql聚簇和非聚簇索引的区别 5. 非聚簇索引一定会回表查询吗? 6. 讲一讲前缀索引? 7. 为什么索引结构默认使用B…...
[技术闲聊]checklist
电路设计完成后,需要确认功能完整性,明确是否符合设计规格需求;需要确认电路设计是否功能符合但是系列项不符合设计规则,如果都没有问题,那么就可以发给layout工程师。 今天主要讲讲电路设计规则,涉及到一…...

力扣刷题 二叉树的迭代遍历
题干 给你二叉树的根节点 root ,返回它节点值的 前序 遍历。 示例 1: 输入:root [1,null,2,3] 输出:[1,2,3]示例 2: 输入:root [] 输出:[]示例 3: 输入:root [1] 输…...

【二】Django小白三板斧
今日内容 静态文件配置 request对象方法初识 pycharm链接数据库(MySQL) django链接数据库(MySQL) Django ORM简介 利用ORM实现数据的增删查改 【一】Django小白三板斧 HttpResponse 返回字符串类型的数据 render 返回HTML文…...

MyBatis的基本应用
源码地址 01.MyBatis环境搭建 添加MyBatis的坐标 <!--mybatis坐标--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.9</version></dependency><!--mysql驱动坐…...

大话软工笔记—需求分析概述
需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...
SciencePlots——绘制论文中的图片
文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了:一行…...

.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

Day131 | 灵神 | 回溯算法 | 子集型 子集
Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣(LeetCode) 思路: 笔者写过很多次这道题了,不想写题解了,大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

C++ 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...

多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...

AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...