Socket编程、协议理解
Socket编程、协议理解
- 简单说明
- Socket编程
- Socket 常用接口
- Socket服务端业务编码
- 代码说明
- 文件服务(fileServe)
- 消息服务(msgServe)
- 消息写会(writeResponse)
- 注意事项
- Socket客户端业务编码
- 代码说明
- 总结
RYP协议:基于TCP/IP协议之上的自定义协议Rocky Protocol。
协议用途:学习并理解顶层协议基础中的基础原理和理论说明。
// 协议 RYP// 协议规定:第一个字节为类型判断,1为文件流 其他为文字流。// 除第一字节后的body体即为传输内容。
简单说明
为了更好的学习Socket,实现Socket的过程中,更好的理解什么是应用层协议,也为了进一步理解协议的概念。
目的:学习Socket编程,了解协议的概念。
语言:Java
协议: 经商讨、协商而制定的多方公共认可的、遵守的约定。
举例:我们中国人讲的话被称作中文,这个就是世界共同认可的,达成共识的。
若你自己创建了一个语言发音,但是只是自己知道不成体系,这不被他人认可的就不能称作有协议的概念。
Socket编程
所谓套接字(Socket),就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制。从所处的地位来讲,套接字上联应用进程,下联网络协议栈,是应用程序通过网络协议进行通信的接口,是应用程序与网络协议栈进行交互的接口。 1
Socket编程,通常是一对套接字之间的通信交互。在下面的实例中,体现出来的双端分别为:服务端、客户端。
服务端:提供接入服务,并提供特有的服务和业务处理,服务端负责消息的接收,业务的处理和结果回写。作为服务端不可自主选择客户端,只能等待客户端的接入来完成服务,类似一个特定功能的应用程序,只为客户端提供特有的服务。
客户端:接入服务端,获取服务端提供的特定功能的服务。客户端可以指定服务端,客户端与客户端之间无法通信。
Socket 常用接口
| 方法名称 | 入参 | 说明 |
|---|---|---|
| getInputStream | void | 获取读流 |
| getOutputStream | void | 获取写流 |
| shutdownInput | void | 说明当前读流已完成,不会在进行读流操作了。is流也会失效。 |
| shutdownOutput | void | 说明当前写流已完成,不会进行写流操作了。os流也会失效。 |
| close | void | 关闭当前连接 |
Socket服务端业务编码
// 协议 RYP// 协议规定:第一个字节为类型判断,1为文件流 其他为文字流。// 除第一字节后的body体即为传输内容public static final String FILE_RES = "服务端回复::文件接收成功 (~v~)";public static final String MSG_RES = "服务端回复::消息已成功接收!";public static void main(String[] args) {try {ServerSocket serverSocket = new ServerSocket(55555);while (true) {System.out.println("服务端接收准备完成...");Socket client = serverSocket.accept();InputStream is = client.getInputStream();byte type = getType(is);if (type == TypeEnums.FILE_TYPE) {fileServe(is);} else {msgServe(is);}client.shutdownInput();writeResponse(client, type);client.close();}} catch (IOException e) {e.printStackTrace();}}/*** 文件服务** @param inputStream* @throws IOException*/private static void fileServe(InputStream inputStream) throws IOException {System.out.println("当前是文件类型!");String filePath = "C:\\log.txt";FileOutputStream fos = new FileOutputStream(filePath);OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");char[] buff = new char[1024];BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));while (br.read(buff) != -1) {String str = new String(buff);osw.write(str);}osw.close();System.out.println("客户端发送文件已接收完成!");}/*** 消息服务** @param is* @throws IOException*/private static void msgServe(InputStream is) throws IOException {InputStreamReader isr = new InputStreamReader(is);BufferedReader br = new BufferedReader(isr);String temp = null;StringBuilder sb = new StringBuilder();while (null != (temp = br.readLine())) {sb.append(temp);}System.out.println("客户端请求:" + sb.toString());}/*** 消息写回** @param client* @param type 业务类型 1 文件 其他:消息* @throws IOException*/private static void writeResponse(Socket client, byte type) throws IOException {OutputStream outputStream = client.getOutputStream();PrintWriter writer = new PrintWriter(outputStream);writer.println(type == 1 ? FILE_RES : MSG_RES);writer.flush();writer.close();}/*** 获取业务类型** @param is* @return* @throws IOException*/private static byte getType(InputStream is) throws IOException {byte[] buf = new byte[1];is.read(buf);return buf[0];}
代码说明
ServerSocket serverSocket = new ServerSocket(55555)
用于定义服务端Socket,需定义一个端口,用于客户端的接入。
accept执行后,动服务端即会进入阻塞状态,当存在客户端接入是就会分配一个连接去响应客户端的请求服务。
在代码用例中可以看到,我们首先通过getType方法读流,当前协议的约定是第一个字节作为判断依据,“1:文件服务类型,其他:消息服务类型”。
在识别类型后作具体的业务判断是文件服务还是消息服务。
文件服务(fileServe)
文件服务实现的特定业务为文件存储,客户端将自己想要存储的文件写到流中,服务端读取到文件后,将文件转储到当前服务器中,类似于文件服务器的服务。(没有写读文件,大致理解就可,有兴趣的可以使用Socket编程写一个简易文件服务)
消息服务(msgServe)
消息服务实现的特定业务较为简单,接收客户端发送的信息,展示处理。
消息写会(writeResponse)
获取os流,回写需要返回给客户端的信息。
注意事项
- 文件使用字符流转储,也可使用字节流,但字节流对于存在中文的情况下,byte[]数组上限的情况下会存在乱码的情况且数据量大的情况下性能极低。
- 文件服务目前只适合传输txt类型的文件,若其他文件可以扩展业务类型使用字节流进行转储。
Socket客户端业务编码
public static final byte FILE_TYPE = 1;public static final byte MSG_TYPE = 2;public static void main(String[] args) {try {long sl = System.currentTimeMillis();Socket socket = new Socket("127.0.0.1", 55235);act(socket, FILE_TYPE);long se = System.currentTimeMillis();System.out.println("总花费时间:" + (se - sl) + "ms");socket.close();} catch (IOException e) {e.printStackTrace();}}/*** 执行器** @param socket* @param type* @throws IOException*/private static void act(Socket socket, byte type) throws IOException {if (type == FILE_TYPE) {transferFile(socket);} else {transferMsg(socket);}}/*** 文件传输** @param socket 套接字* @throws IOException*/public static void transferFile(Socket socket) throws IOException {System.out.println("客户端准备传输文件...");String filePath = "C:\\Users\\rock\\Desktop\\test.txt";OutputStream outputStream = socket.getOutputStream();outputStream.write(FILE_TYPE);outputStream.write(fileConvertToByteArray(new File(filePath)));socket.shutdownOutput();response(socket.getInputStream());}/*** 消息传输** @param socket 套接字*/public static void transferMsg(Socket socket) throws IOException {System.out.println("客户端准备传输消息...");String msg = "This is test msg";OutputStream outputStream = socket.getOutputStream();outputStream.write(MSG_TYPE);outputStream.write(msg.getBytes());socket.shutdownOutput();response(socket.getInputStream());}/*** 封装回复信息通知** @param inputStream 读流* @throws IOException*/public static void response(InputStream inputStream) throws IOException {InputStreamReader isr = new InputStreamReader(inputStream);BufferedReader br = new BufferedReader(isr);String temp = null;StringBuilder sb = new StringBuilder();while (null != (temp = br.readLine())) {sb.append(temp);}System.out.println(sb.toString());}/*** 文件转byte流** @param file 文件信息* @return*/private static byte[] fileConvertToByteArray(File file) {byte[] data = null;try {FileInputStream fis = new FileInputStream(file);ByteArrayOutputStream baos = new ByteArrayOutputStream();int len;byte[] buffer = new byte[1024];while ((len = fis.read(buffer)) != -1) {baos.write(buffer, 0, len);}data = baos.toByteArray();fis.close();baos.close();} catch (Exception e) {e.printStackTrace();}return data;}
代码说明
Socket socket = new Socket(“127.0.0.1”, 55555);
客户端创建连接时,需要指定服务端的IP和端口,这也是套接字的组成。
使用os流将需要的信息写入到流中,传入服务端。(根据协议的约定组装流数据)
无论是文件还是字符串都将转为字节流进行传输。
客户端的处理比服务端来讲,过程简单,也容易理解。
因为客户端是使用功能的一方,只需要传入约定的数据,获得对应的服务即可。
总结
至此,我们就简单的实现了Socket编程,以及完成了一个基于TCP/IP协议实现了另一套协议的约定的内容。之后再次进行应用协议的学习可能有更好的理论基础,因底层原理基本类似,只是顶层设计更为复杂,约定内容更为精细,职能更为清晰。
希望各位对Socket和协议有一个更加清晰的认知
王雷,TCP/IP网络编程基础教程,北京理工大学出版社,2017.02,第4页 ↩︎
相关文章:
Socket编程、协议理解
Socket编程、协议理解简单说明Socket编程Socket 常用接口Socket服务端业务编码代码说明文件服务(fileServe)消息服务(msgServe)消息写会(writeResponse)注意事项Socket客户端业务编码代码说明总结RYP协议:基于TCP/IP协议之上的自定义协议Rocky Protocol。 协议用途&…...
Idea集成码云
1:Idea集成码云1.1:IDEA安装码云插件【第一步】Idea 默认不带码云插件, 我们第一步要安装 Gitee 插件。如图所示, 在 Idea 插件商店搜索 Gitee,然后点击右侧的 Install 按钮。安装成功后,重启 Idea。Idea 重…...
并发编程学习篇ReentrantLock设计思想剖析
一、AQS原理剖析 什么是AQS java.util.concurrent包中的大多数同步器实现都是围绕着共同的基础行为,比如 等待队列、条件队列、独占获取、共享获取等而这些行为的抽象就是基于AbstractQueuedSynchronizer(简称AQS)实现的,AQS是一…...
区分效度全流程分析
基本说明 区分效度(又称判别效度、区别效度),其实质也是一种结构效度。区分效度强调本不应该在同一因子的测量项,确实不在同一因子下面。比如说,测量项A和 B分别测量两个属性,应该分属于因子A和因子B中&…...
【华为OD机试模拟题】用 C++ 实现 - 找数字(2023.Q1)
最近更新的博客 华为OD机试 - 入栈出栈(C++) | 附带编码思路 【2023】 华为OD机试 - 箱子之形摆放(C++) | 附带编码思路 【2023】 华为OD机试 - 简易内存池 2(C++) | 附带编码思路 【2023】 华为OD机试 - 第 N 个排列(C++) | 附带编码思路 【2023】 华为OD机试 - 考古…...
从0开始写Vue项目-Vue实现用户数据批量上传和数据导出
从0开始写Vue项目-环境和项目搭建_慕言要努力的博客-CSDN博客从0开始写Vue项目-Vue2集成Element-ui和后台主体框架搭建_慕言要努力的博客-CSDN博客从0开始写Vue项目-Vue页面主体布局和登录、注册页面_慕言要努力的博客-CSDN博客从0开始写Vue项目-SpringBoot整合Mybatis-plus实现…...
企业容器云管理平台选型指南
作者简介 涂家英,SUSE 资深架构师,专注 Cloud-Native 相关产品和解决方案设计,在企业级云原生平台建设领域拥有丰富的经验。 数字时代下的容器云管理平台 数字时代,市场竞争加剧,业务需求日新月异,敏态 IT…...
OpenGL超级宝典学习笔记:着色器存储区块、原子内存操作、内存屏障
前言 本篇在讲什么 本篇为蓝宝书学习笔记 着色器存储区块 原子内存操作 内存屏障 本篇适合什么 适合初学Open的小白 本篇需要什么 对C语法有简单认知 对OpenGL有简单认知 最好是有OpenGL超级宝典蓝宝书 依赖Visual Studio编辑器 本篇的特色 具有全流程的图文教学 重…...
SpringMVC框架知识详解(入门版)
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...
25-动画和过渡
动画和过渡 一、动画 使用css动画样式,配合vue实现动画效果。 编写模板 <template><div><button click"isShow !isShow">显示/隐藏</button><h1 v-show"isShow">你好啊</h1></div> </templa…...
Linux 操作系统原理 — 虚拟内存管理
目录 文章目录 目录虚拟内存技术页式内存管理技术x86_32 CPU 虚拟内存虚拟地址格式与内核页表虚拟内存空间Kernel SpaceUser Spacex86_64 CPU 虚拟内存虚拟地址格式与内核页表(四级页表)虚拟内存空间TLB 缓冲(快表)进程页表虚拟内存技术 虚拟内存技术是操作系统实现的一种…...
保持超低温环境新方法:功耗降至十分之一!
(图片来源:网络)量子比特是量子计算机的主要构建部分,然而热量会导致量子比特容易出错,因此量子系统通常保存在超低温稀释制冷机内,可以将温度保持在绝对零度(−273.15℃)以上。但是…...
论文投稿指南——中文核心期刊推荐(音乐)
【前言】 🚀 想发论文怎么办?手把手教你论文如何投稿!那么,首先要搞懂投稿目标——论文期刊 🎄 在期刊论文的分布中,存在一种普遍现象:即对于某一特定的学科或专业来说,少数期刊所含…...
es-10搜索推荐suggest
搜索推荐:Suggest 概述 搜索一般都会要求具有“搜索推荐”或者叫“搜索补全”的功能,即在用户输入搜索的过程中,进行自动补全或者纠错。以此来提高搜索文档的匹配精准度,进而提升用户的搜索体验,这就是Suggest。 四…...
VMware ESXi 7.0 Update 3k - 领先的裸机 Hypervisor (sysin Custom Image)
VMware ESXi 7.0 Update 3k - 领先的裸机 Hypervisor (sysin Custom Image) VMware ESXi 7.0 Update 3k Standard & All Custom Image for ESXi 7.0 U3k Install CD 请访问原文链接:https://sysin.org/blog/vmware-esxi-7-u3/,查看最新版。原创作品…...
JVM整体分析篇
这里写目录标题JVM的组成部分1.类装载子系统1.1一个类加载到JVM的过程1.2类加载机制1.3为什么设计双亲委派机制1.4怎么打破双亲委派机制2.运行时数据区2.1线程私有及共享2.2JVM内存区结构2.3JVM参数设置经验3.Java对象的生命周期3.1.对象的创建3.2.对象大小的计算(6…...
【Python入门第十七天】Python While 循环
Python 循环 Python 有两个原始的循环命令: while 循环for 循环 while 循环 如果使用 while 循环,只要条件为真,我们就可以执行一组语句。 实例 只要 i 小于 7,打印 i: i 1 while i < 7:print(i)i 1运行实…...
怎样激发读者好奇心?短视频营销之场景化
目录 激发读者好奇心?四个小技巧帮你搞定 1.省略法 2.欲言又止法: 3.问句法:就是用疑问的形式引起别人的好奇。 4.反差法 选择合适的主题。 利用场景化效果 使用滤镜。 如何提高用户的留存率。 1、设置一个有趣的话题。 2、用好道具。 3、多用竖屏。 什…...
【LeetCode】剑指 Offer 14- II. 剪绳子 II p96 -- Java Version
题目链接:https://leetcode.cn/problems/jian-sheng-zi-ii-lcof/ 1. 题目介绍(14- II. 剪绳子 II) 给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1)&…...
【红黑树】红黑树插入操作相关的细节和疑难拆解分析
本文就红黑树的插入操作进行细致到每一个小步骤的解析。1,成员变量本红黑树使用了三叉链结构,使用的时候尤其要记得处理指向父亲的指针。为何在节点的构造函数中,默认节点的颜色为红色?因为考虑到红黑树的性质(对于每个…...
第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...
国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
java 实现excel文件转pdf | 无水印 | 无限制
文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...
(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...
实现弹窗随键盘上移居中
实现弹窗随键盘上移的核心思路 在Android中,可以通过监听键盘的显示和隐藏事件,动态调整弹窗的位置。关键点在于获取键盘高度,并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...
【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...
AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...
视觉slam十四讲实践部分记录——ch2、ch3
ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...
安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲
文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...
MySQL JOIN 表过多的优化思路
当 MySQL 查询涉及大量表 JOIN 时,性能会显著下降。以下是优化思路和简易实现方法: 一、核心优化思路 减少 JOIN 数量 数据冗余:添加必要的冗余字段(如订单表直接存储用户名)合并表:将频繁关联的小表合并成…...
