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

四十三、网络编程(下)——TCP 编程与 HTTP 入门

痛点引入UDP 发出去就不管了万一丢包怎么办文件上传必须每字节都不能少TCP 协议应运而生——面向连接、可靠传输、三次握手确认☎️下篇手写 TCP 客户端-服务端、文件上传、多线程并发服务器最后揭秘网页背后的 HTTP 协议一、TCP 协议——面向连接的「电话」☎️1.1 回顾UDP vs TCP对比项UDP上篇TCP本篇连接性无连接 ❌面向连接 ✅可靠性不可靠可能丢包可靠确认机制✅效率高较低类比发短信、寄信 打电话 ☎️区分发送端 / 接收端客户端 / 服务端1.2 TCP 三次握手面试必问客户端 服务端 | | | ① SYN (我想连接) | | ----------------------------- | | | | ② SYNACK (可以我也准备好了) | | ----------------------------- | | | | ③ ACK (收到开始传数据) | | ----------------------------- | | | ✅ 三次握手完成连接建立为什么是三次两次可能死锁服务端以为连上了客户端其实没收到确认三次才能保证双方都说清楚二、TCP 核心类 2.1 两个套接字类名角色作用获取方式Socket客户端套接字连接服务端、发送/接收数据new Socket(ip, port)ServerSocket服务端套接字监听端口、接收客户端连接new ServerSocket(port)2.2 核心方法速查Socket 常用方法方法功能getInputStream()获取输入流读取对方发来的数据 getOutputStream()获取输出流向对方发送数据 shutdownOutput()关闭输出流发送结束标记⚠️close()关闭连接ServerSocket 常用方法方法功能accept()接收客户端连接返回客户端 Socket阻塞2.3 数据交互方式客户端发送 → 服务端读取 客户端getOutputStream().write(...) 服务端getInputStream().read(...) 客户端读取 ← 服务端发送 客户端getInputStream().read(...) 服务端getOutputStream().write(...)三、TCP 基本通信 3.1 客户端代码importjava.net.Socket;importjava.io.OutputStream;publicclassTCP_Client{publicstaticvoidmain(String[]args)throwsException{// ⚠️ new Socket() 就会触发三次握手// 成功说明连接建立 ✅失败抛出异常SocketsnewSocket(192.168.26.23,8888);// 发送消息给服务端OutputStreamoss.getOutputStream();os.write(江总你好.getBytes());s.close();System.out.println(客户端发送完成☎️);}}3.2 服务端代码importjava.net.ServerSocket;importjava.net.Socket;importjava.io.InputStream;publicclassTCP_Server{publicstaticvoidmain(String[]args)throwsException{System.out.println(服务端启动等待连接...);// 1. 创建服务端指定端口ServerSocketssnewServerSocket(8888);// 2. accept() 阻塞等待客户端连接Socketclientss.accept();System.out.println(客户端已连接client.getInetAddress());// 3. 读取客户端消息InputStreamisclient.getInputStream();byte[]bufnewbyte[1024];intlenis.read(buf);// read() 阻塞直到读完StringmsgnewString(buf,0,len);System.out.println(收到msg);client.close();}}3.3 ⚠️ TCP 编程注意点服务端必须先启动否则客户端连接失败new Socket()触发三次握手服务端没启动就抛异常accept()阻塞直到有客户端连接read()阻塞直到读到数据或对方关闭流四、TCP 双向通信 4.1 服务端收消息 回复importjava.net.*;importjava.io.*;importjava.util.Scanner;publicclassTCP_ServerPro{publicstaticvoidmain(String[]args)throwsException{ServerSocketssnewServerSocket(8888);ScannerscnewScanner(System.in);System.out.println(服务端启动...);Socketclientss.accept();System.out.println(客户端连接client.getInetAddress());while(true){// 1. 读取客户端消息InputStreamisclient.getInputStream();byte[]bufnewbyte[1024];intlenis.read(buf);StringmsgnewString(buf,0,len);System.out.println(客户端msg);// 2. 回复客户端System.out.print(请输入回复);Stringreplysc.next();OutputStreamosclient.getOutputStream();os.write(reply.getBytes());}}}4.2 客户端发消息 收回复importjava.net.*;importjava.io.*;importjava.util.Scanner;publicclassTCP_ClientPro{publicstaticvoidmain(String[]args)throwsException{SocketsnewSocket(192.168.26.23,8888);ScannerscnewScanner(System.in);while(true){// 1. 发送消息System.out.print(请输入消息);Stringmsgsc.next();OutputStreamoss.getOutputStream();os.write(msg.getBytes());// 2. 接收服务端回复InputStreamiss.getInputStream();byte[]bufnewbyte[1024];intlenis.read(buf);System.out.println(服务端回复newString(buf,0,len));}}}五、TCP 文件上传 5.1 需求客户端上传图片到服务端服务端保存后给客户端响应。5.2 客户端读文件 上传importjava.net.*;importjava.io.*;publicclassTCP_FileClient{publicstaticvoidmain(String[]args)throwsException{SocketsnewSocket(127.0.0.1,9999);// 1. 读取本地文件FileInputStreamfisnewFileInputStream(D:/1.jpg);OutputStreamoss.getOutputStream();// 2. 循环写出上传文件数据byte[]bufnewbyte[1024];intlen;while((lenfis.read(buf))!-1){os.write(buf,0,len);}// ⚠️ 关键告诉服务端我传完了s.shutdownOutput();fis.close();// 3. 读取服务端响应InputStreamiss.getInputStream();byte[]respBufnewbyte[1024];intrespLenis.read(respBuf);System.out.println(服务端newString(respBuf,0,respLen));s.close();}}5.3 服务端收文件 保存 响应importjava.net.*;importjava.io.*;importjava.util.Random;publicclassTCP_FileServer{publicstaticvoidmain(String[]args)throwsException{ServerSocketssnewServerSocket(9999);System.out.println(文件服务器启动...);Socketclientss.accept();System.out.println(客户端上传client.getInetAddress());// 1. 读取客户端上传数据InputStreamisclient.getInputStream();// 2. 生成随机文件名防止覆盖RandomrnewRandom();FileOutputStreamfosnewFileOutputStream(D:/upload/r.nextInt(Integer.MAX_VALUE).jpg);byte[]bufnewbyte[1024];intlen;while((lenis.read(buf))!-1){fos.write(buf,0,len);// 保存到磁盘}fos.close();// 3. 给客户端响应OutputStreamosclient.getOutputStream();os.write(上传成功✅.getBytes());client.close();}}5.4 ⚠️ shutdownOutput() —— 文件上传的灵魂不用 shutdownOutput() 服务端 read() 永远阻塞不知道客户端传完了 用了 shutdownOutput() 客户端调用后发送一个结束标记 服务端 read() 收到 -1跳出循环 ✅一句话shutdownOutput() 告诉对方我说完了你可以处理了六、TCP 多线程并发服务器 6.1 为什么需要多线程单线程服务器 客户端A 连接 → 服务器处理A → 处理完才能处理B → 客户端B 等着体验极差 ❌ 多线程服务器 客户端A 连接 → 开线程1 处理A 客户端B 连接 → 开线程2 处理B → 同时处理互不影响 ✅6.2 多线程服务端代码importjava.net.*;importjava.io.*;importjava.util.Random;publicclassTCP_MultiThreadServer{publicstaticvoidmain(String[]args)throwsException{ServerSocketssnewServerSocket(9999);System.out.println(多线程服务器启动...);while(true){Socketclientss.accept();// 等待客户端System.out.println(新客户端client.getInetAddress());// 为每个客户端开启独立线程newThread(()-{try{// 接收文件InputStreamisclient.getInputStream();RandomrnewRandom();FileOutputStreamfosnewFileOutputStream(D:/upload/r.nextInt(Integer.MAX_VALUE).jpg);byte[]bufnewbyte[1024];intlen;while((lenis.read(buf))!-1){fos.write(buf,0,len);}fos.close();// 响应客户端OutputStreamosclient.getOutputStream();os.write(上传成功✅.getBytes());client.close();System.out.println(客户端上传完成);}catch(Exceptione){e.printStackTrace();}}).start();// 启动线程}}}6.3 启动多个客户端测试publicclassTCP_MultiClientTest{publicstaticvoidmain(String[]args){// 同时启动 3 个客户端并发上传for(inti0;i3;i){newThread(()-{try{SocketsnewSocket(127.0.0.1,9999);FileInputStreamfisnewFileInputStream(D:/1.jpg);OutputStreamoss.getOutputStream();byte[]bufnewbyte[1024];intlen;while((lenfis.read(buf))!-1){os.write(buf,0,len);}fis.close();s.shutdownOutput();// 接收响应InputStreamiss.getInputStream();byte[]respnewbyte[1024];intrespLenis.read(resp);System.out.println(Thread.currentThread().getName()newString(resp,0,respLen));s.close();}catch(Exceptione){e.printStackTrace();}}).start();}}} 多线程上传优势多个客户端同时上传✅每个客户端独占线程互不干扰服务端持续运行不用重启七、HTTP 协议入门——网页背后的原理 7.1 HTTP 是什么HTTPHyperText Transfer Protocol超文本传输协议应用层最常用的协议。7.2 HTTP 请求格式GET /index.html HTTP/1.1 ← 请求行方法 路径 版本 Host: www.example.com ← 请求头 User-Agent: Mozilla/5.0 ← 空行必须 [请求体] ← GET 请求通常没有7.3 HTTP 响应格式HTTP/1.1 200 OK ← 状态行版本 状态码 消息 Content-Type: text/html ← 响应头 Content-Length: 1234 ← 空行必须 html.../html ← 响应体网页内容7.4 常见状态码状态码含义200请求成功 ✅301永久重定向302临时重定向404资源未找到 ❌500服务器内部错误 ⚠️7.5 TCP 与 HTTP 的关系TCP 是传输层协议 → 负责可靠传输数据 ☎️ ↓ HTTP 是应用层协议 → 定义数据格式请求头/响应头 ↓ HTTP 底层使用 TCP 传输一句话HTTP 带格式的 TCP本篇总结 TCP 协议☎️面向连接、可靠传输、三次握手确认三次握手SYN → SYNACK → ACK保证双方都确认连接Socket vs ServerSocket客户端new Socket(ip,port)、服务端new ServerSocket(port)accept()数据交互getInputStream()读、getOutputStream()写TCP 双向通信客户端发→服务端收→服务端回→客户端收文件上传客户端读文件写服务端 shutdownOutput()发送结束标记多线程服务器while(true) { accept(); new Thread(...).start(); }支持并发HTTP 协议应用层协议定义请求/响应格式底层用 TCP 传输作者书源丶发布平台CSDN

相关文章:

四十三、网络编程(下)——TCP 编程与 HTTP 入门

😫 痛点引入:UDP 发出去就不管了,万一丢包怎么办?文件上传必须每字节都不能少! TCP 协议应运而生——面向连接、可靠传输、三次握手确认!☎️ 下篇手写 TCP 客户端-服务端、文件上传、多线程并发服务器&…...

梳理一下前端模块化规范:CommonJS ESM AMD CMD UMD

前端模块化规范在发展过程中出现过多种规范,大多开发者都对这些名词有个印象,但问起来又有些模糊。本文的目的是做一个梳理,帮助记忆。先上一张对比表:类型核心定位语法关键词适用环境特点CommonJS(CJS)Nod…...

AUTOSAR: RTE概述

类比:RTE就类似于电话接线员(向他人打电话先将电话信息传给接线员,再由接线员传给被接受人)。RTE管理SWC与SWC之间、SWC与BSW之间的通信信息。比如,SWC1要将信息传给SWC2,可SWC2正在执行任务,RT…...

【PAT甲级真题】- Elevator(20)

题目来源 Elevator 题目描述点击链接自行查看 注意点: 停在同一层时多等5秒 Description The highest building in our city has only one elevator. A request list is made up with N positive numbers. The numbers denote at which floors the elevator will…...

告别Keil默认丑字体!手把手教你配置VS Code同款暗黑主题(附global.prop文件)

告别Keil默认丑字体!手把手教你配置VS Code同款暗黑主题(附global.prop文件) 作为一名嵌入式开发者,每天面对Keil那套灰白单调的编辑器界面,眼睛的疲劳感总是来得特别快。尤其当你在VS Code的暗黑主题下写完前端代码&a…...

别再复制粘贴了!程序员必备的Unicode汉字符号速查表(含一键复制)

程序员必备的Unicode汉字符号高效输入指南 1. 为什么需要掌握Unicode汉字符号? 在日常开发工作中,我们经常需要在代码注释、文档说明或UI界面中添加一些特殊符号来增强表达效果。比如用箭头符号表示流程走向,用数学符号展示公式逻辑&#xff…...

鸿蒙NEXT开发从零到一:手把手搭建开发环境并发布第一个应用

系列文章:鸿蒙NEXT开发实战系列 -- 第1篇(共5篇) 适合人群:零基础入门,或有 Android/iOS 经验的开发者 开发环境:DevEco Studio 5.0.5 | HarmonyOS NEXT (API 14) 阅读时长:约30分钟 上一篇&…...

AS5600磁编码器避坑指南:从I2C通信失败到角度跳变的5个常见问题及解决方法

AS5600磁编码器实战避坑手册:5个高频故障的工程级解决方案 磁编码器在电机控制、机器人关节定位等场景中扮演着关键角色,而AS5600凭借其高性价比和I2C接口的便利性成为许多工程师的首选。但在实际部署中,从I2C通信失败到角度跳变等问题常常让…...

吃透C++ AVL树:原理+完整实现,新手也能轻松上手

文章目录 前言一、先搞懂:什么是AVL树?核心特性是什么?二、AVL树的C完整实现(新手可直接复制运行)三、AVL树的删除操作(可选,进阶内容)四、AVL树的性能与应用场景五、新手常见误区&a…...

为AI编码助手集成sh-guard:语义化Shell命令安全防护实践

1. 项目概述:为AI编码助手装上“安全刹车”最近在折腾各种AI编码助手,从Cursor到Claude Code,再到本地部署的Codex,效率提升确实肉眼可见。但用久了,心里总有点发毛——这些AI助手动动嘴皮子就能执行rm -rf、curl | ba…...

别再让Excel导入报错!用EasyExcel+自定义监听器搞定6种数据校验(附完整代码)

用EasyExcel构建企业级Excel导入校验体系的实战指南 每次运营人员上传Excel表格时,后台服务就像在拆盲盒——你永远不知道会收到格式混乱的数据、缺失的字段还是重复的记录。传统的数据校验方式往往在全部读取完成后才进行验证,这不仅浪费服务器资源&…...

开源机械爪项目全解析:从设计到ROS集成

1. 项目概述:一个开源协作的“机械爪”项目最近在GitHub上闲逛,发现了一个挺有意思的项目,叫lambertse/openclaw-lambertse-team。光看名字,你可能会有点懵,这“openclaw”是啥?“lambertse-team”又是谁&a…...

从码农到架构师:Boss-Skill项目揭示全栈开发者进阶之路

1. 项目概述与核心价值最近在GitHub上看到一个挺有意思的项目,叫boss-skill。乍一看这个标题,你可能会联想到职场生存指南或者游戏里的BOSS技能。但实际上,这是一个面向开发者的、旨在提升“老板级”开发效率与工程能力的工具集或知识库。作为…...

Token需求狂飙千倍,22亿热钱涌向这家AGI Infra头号玩家

衡宇 发自 凹非寺量子位 | 公众号 QbitAI在今年的GTC大会上,黄仁勋宣告:英伟达已不再局限于一家芯片或 GPU 公司,而是全面转型为全栈式 AI 基础设施公司。这让“AI基础设施”再度站在了行业的风口中央。事实上,早在风口来临之前&a…...

从PasteJacker工具看剪贴板劫持:在Kali Linux上复现一次无害攻击(仅供学习)

从PasteJacker工具看剪贴板劫持:在Kali Linux上复现一次无害攻击(仅供学习) 剪贴板劫持作为一种隐蔽性极强的攻击手段,近年来在网络安全事件中频繁出现。这种攻击利用了用户对复制粘贴操作的天然信任,通过篡改剪贴板内…...

别再混淆WT和WO了!图解SAP EWM仓库任务与订单的核心逻辑与配置实例

别再混淆WT和WO了!图解SAP EWM仓库任务与订单的核心逻辑与配置实例 在SAP EWM的世界里,仓库任务(WT)和仓库订单(WO)就像快递行业的包裹与派送路线——前者承载具体货物信息,后者规划执行路径。许…...

别再傻傻分不清!医疗器械UDI码里的DI和PI,到底怎么用?

医疗器械UDI码实战指南:DI与PI的精准解析与应用 在医疗器械行业,UDI码就像产品的"身份证",而其中的DI和PI则是这张身份证上最关键的信息区块。许多从业者虽然每天都在扫描这些条形码,却未必真正理解如何高效利用这两组数…...

别再死记硬背了!用Wireshark抓包实战,5分钟搞懂PCIe配置空间的BAR寄存器

用Wireshark透视PCIe配置空间:BAR寄存器实战解析手册 第一次接触PCIe设备的BAR寄存器时,我盯着那些十六进制数值看了整整一个下午。直到在Wireshark里亲眼看到BIOS通过TLP数据包与设备协商地址空间的过程,那些抽象的概念才突然变得鲜活起来。…...

Stackmoss:构建生产级AI原生应用的一体化框架实战指南

1. 项目概述与核心价值最近在开源社区里,Stackmoss 这个项目引起了我的注意。它不是一个简单的工具库,而是一个旨在构建“AI原生应用”的完整技术栈。简单来说,它想解决的问题是:当你想开发一个真正由AI驱动、而非仅仅调用API的应…...

别再只盯着RGB了!手把手教你用奥比中光Astra SDK获取并可视化深度图(VS2022环境配置)

深度视觉开发实战:用奥比中光Astra SDK解锁3D感知新维度 当RGB摄像头已经成为智能设备的标配,另一种"视觉"正在悄然改变我们与机器交互的方式——深度感知。不同于传统摄像头记录的色彩信息,深度相机捕捉的是每个像素点到相机的实际…...

IrisSupportLib线程管理与事件处理机制深度解析

1. IrisSupportLib线程管理机制解析在复杂系统开发中,线程管理往往是最具挑战性的环节之一。IrisSupportLib通过一系列精心设计的接口,为开发者提供了细粒度的线程控制能力。我们先来看最核心的线程终止接口:1.1 stopThreads()的工程实践stop…...

Jetson Xavier NX上编译OpenCV 4.5.3支持CUDA加速,保姆级避坑指南(含libjasper-dev问题解决)

Jetson Xavier NX上编译OpenCV 4.5.3支持CUDA加速的完整避坑指南 作为一名长期在边缘计算设备上部署计算机视觉方案的开发者,我深知在Jetson Xavier NX这类嵌入式平台上编译OpenCV的痛点。本文将分享我多次实战后总结的保姆级避坑方案,特别是针对CUDA加速…...

FPGA流水线FFT IP核生成器:dblclockfft配置与实战指南

1. 项目概述:一个高度可配置的流水线FFT IP核生成器最近在折腾一个FPGA上的信号处理项目,需要用到快速傅里叶变换(FFT)这个核心算法。大家都知道,FFT是数字信号处理的基石,从音频处理到通信解调&#xff0c…...

别再死磕神经网络了!用Python+scikit-fuzzy手把手教你实现一个模糊恒温控制器

用Pythonscikit-fuzzy实现智能恒温控制:从模糊逻辑到落地实践 想象一下,你精心布置的热带鱼缸需要保持26℃的恒定水温。传统温控器要么全功率加热直到达到阈值(导致温度波动),要么需要复杂的PID参数调校。而模糊控制却…...

SOAFEE:云原生技术如何重塑汽车嵌入式软件开发

1. 项目概述:当汽车软件遇上云原生如果你在汽车电子或嵌入式软件领域摸爬滚打过几年,一定对“开发-测试-集成-标定”这个漫长且昂贵的循环深有体会。一套新的ADAS算法,从云端写好代码,到最终能在实车的域控制器上稳定、安全地跑起…...

从硬件工程师视角看安卓手机:可编程平台、传感器融合与生态系统

1. 从“能打电话就行”到“数字瑞士军刀”:我的安卓手机深度体验与思考作为一名在电子设计自动化(EDA)和可编程逻辑领域摸爬滚打了二十多年的工程师,我的工具箱里塞满了各种开发板、逻辑分析仪和仿真软件。长久以来,我…...

HST-Bench:人类解题耗时评估数据集构建与应用

1. 项目背景与核心价值去年参与某智能体评估项目时,我们团队曾陷入一个尴尬境地——现有基准测试集无法真实反映人类解决问题的实际耗时。当算法在标准数据集上跑出"5秒完成"的漂亮成绩时,实际业务场景中用户可能需要花费3分钟才能解决相同问题…...

旧电脑别扔!手把手教你用U盘把OpenWrt刷成软路由(保姆级教程)

旧电脑重生计划:用OpenWrt打造高性能软路由全指南 家里那台积灰多年的旧笔记本或迷你主机,除了卖废铁还能做什么?今天我要分享一个让老旧硬件重获新生的绝佳方案——将它们改造成专业级软路由。不同于普通家用路由器,基于OpenWrt的…...

Qt 3D实战:如何给你的三维场景添加第一人称和环绕相机控制器(Qt 5.15.2)

Qt 3D相机控制实战:打造沉浸式交互体验的五大核心策略 在三维可视化应用中,相机控制就像用户的眼睛和双手,直接决定了交互体验的流畅度与沉浸感。当开发者使用Qt 3D构建模型查看器、设计工具或简单游戏时,如何选择合适的相机控制器…...

Keil uVision仿真器进阶:如何正确配置外部时钟与查看SYSCLK频率

Keil uVision仿真器进阶:如何正确配置外部时钟与查看SYSCLK频率 在嵌入式开发中,时钟配置是确保系统稳定运行的关键环节。对于使用Keil uVision进行开发的工程师来说,当没有实际硬件板卡时,仿真器成为了验证代码逻辑的重要工具。然…...