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

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 常用接口

方法名称入参说明
getInputStreamvoid获取读流
getOutputStreamvoid获取写流
shutdownInputvoid说明当前读流已完成,不会在进行读流操作了。is流也会失效。
shutdownOutputvoid说明当前写流已完成,不会进行写流操作了。os流也会失效。
closevoid关闭当前连接

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流,回写需要返回给客户端的信息。

注意事项

  1. 文件使用字符流转储,也可使用字节流,但字节流对于存在中文的情况下,byte[]数组上限的情况下会存在乱码的情况且数据量大的情况下性能极低。
  2. 文件服务目前只适合传输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和协议有一个更加清晰的认知


  1. 王雷,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动画样式&#xff0c;配合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 缓冲(快表)进程页表虚拟内存技术 虚拟内存技术是操作系统实现的一种…...

保持超低温环境新方法:功耗降至十分之一!

&#xff08;图片来源&#xff1a;网络&#xff09;量子比特是量子计算机的主要构建部分&#xff0c;然而热量会导致量子比特容易出错&#xff0c;因此量子系统通常保存在超低温稀释制冷机内&#xff0c;可以将温度保持在绝对零度&#xff08;−273.15℃&#xff09;以上。但是…...

论文投稿指南——中文核心期刊推荐(音乐)

【前言】 &#x1f680; 想发论文怎么办&#xff1f;手把手教你论文如何投稿&#xff01;那么&#xff0c;首先要搞懂投稿目标——论文期刊 &#x1f384; 在期刊论文的分布中&#xff0c;存在一种普遍现象&#xff1a;即对于某一特定的学科或专业来说&#xff0c;少数期刊所含…...

es-10搜索推荐suggest

搜索推荐&#xff1a;Suggest 概述 搜索一般都会要求具有“搜索推荐”或者叫“搜索补全”的功能&#xff0c;即在用户输入搜索的过程中&#xff0c;进行自动补全或者纠错。以此来提高搜索文档的匹配精准度&#xff0c;进而提升用户的搜索体验&#xff0c;这就是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 请访问原文链接&#xff1a;https://sysin.org/blog/vmware-esxi-7-u3/&#xff0c;查看最新版。原创作品…...

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.对象大小的计算&#xff08;6…...

【Python入门第十七天】Python While 循环

Python 循环 Python 有两个原始的循环命令&#xff1a; while 循环for 循环 while 循环 如果使用 while 循环&#xff0c;只要条件为真&#xff0c;我们就可以执行一组语句。 实例 只要 i 小于 7&#xff0c;打印 i&#xff1a; i 1 while i < 7:print(i)i 1运行实…...

怎样激发读者好奇心?短视频营销之场景化

目录 激发读者好奇心&#xff1f;四个小技巧帮你搞定 1.省略法 2.欲言又止法: 3.问句法:就是用疑问的形式引起别人的好奇。 4.反差法 选择合适的主题。 利用场景化效果 使用滤镜。 如何提高用户的留存率。 1、设置一个有趣的话题。 2、用好道具。 3、多用竖屏。 什…...

【LeetCode】剑指 Offer 14- II. 剪绳子 II p96 -- Java Version

题目链接&#xff1a;https://leetcode.cn/problems/jian-sheng-zi-ii-lcof/ 1. 题目介绍&#xff08;14- II. 剪绳子 II&#xff09; 给你一根长度为 n 的绳子&#xff0c;请把绳子剪成整数长度的 m 段&#xff08;m、n都是整数&#xff0c;n>1并且m>1&#xff09;&…...

【红黑树】红黑树插入操作相关的细节和疑难拆解分析

本文就红黑树的插入操作进行细致到每一个小步骤的解析。1&#xff0c;成员变量本红黑树使用了三叉链结构&#xff0c;使用的时候尤其要记得处理指向父亲的指针。为何在节点的构造函数中&#xff0c;默认节点的颜色为红色&#xff1f;因为考虑到红黑树的性质&#xff08;对于每个…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

<6>-MySQL表的增删查改

目录 一&#xff0c;create&#xff08;创建表&#xff09; 二&#xff0c;retrieve&#xff08;查询表&#xff09; 1&#xff0c;select列 2&#xff0c;where条件 三&#xff0c;update&#xff08;更新表&#xff09; 四&#xff0c;delete&#xff08;删除表&#xf…...

ubuntu搭建nfs服务centos挂载访问

在Ubuntu上设置NFS服务器 在Ubuntu上&#xff0c;你可以使用apt包管理器来安装NFS服务器。打开终端并运行&#xff1a; sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享&#xff0c;例如/shared&#xff1a; sudo mkdir /shared sud…...

MFC内存泄露

1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

CMake基础:构建流程详解

目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享

文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的&#xff0c;根据Excel列的需求预估的工时直接打骨折&#xff0c;不要问我为什么&#xff0c;主要…...

Nuxt.js 中的路由配置详解

Nuxt.js 通过其内置的路由系统简化了应用的路由配置&#xff0c;使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

反射获取方法和属性

Java反射获取方法 在Java中&#xff0c;反射&#xff08;Reflection&#xff09;是一种强大的机制&#xff0c;允许程序在运行时访问和操作类的内部属性和方法。通过反射&#xff0c;可以动态地创建对象、调用方法、改变属性值&#xff0c;这在很多Java框架中如Spring和Hiberna…...

有限自动机到正规文法转换器v1.0

1 项目简介 这是一个功能强大的有限自动机&#xff08;Finite Automaton, FA&#xff09;到正规文法&#xff08;Regular Grammar&#xff09;转换器&#xff0c;它配备了一个直观且完整的图形用户界面&#xff0c;使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...