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

注意事项

  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编程、协议理解相关推荐

  1. Socket编程模式理解与对比

    本文主要分析了几种Socket编程的模式.主要包括基本的阻塞Socket.非阻塞Socket.I/O多路复用.其中,阻塞和非阻塞是相对于套接字来说的,而其他的模式本质上来说是基于Socket的并发模式 ...

  2. socket编程——进一步理解accept函数

    在前面的文章<TCP套接字编程--常用函数小结>中,我们分析了socket的常用函数,其他的函数,我们还比较容易理解,但是accept函数的意义容易被忽略.我们来总结下使用要点: 1)ac ...

  3. Python 中最全面的 Socket 编程指南

    (点击上方公众号,可快速关注一起学Python) 翻译:  keelii   链接: https://keelii.com/2018/09/24/socket-programming-in-pytho ...

  4. Python Socket 编程——聊天室示例程序

    上一篇 我们学习了简单的 Python TCP Socket 编程,通过分别写服务端和客户端的代码了解基本的 Python Socket 编程模型.本文再通过一个例子来加强一下对 Socket 编程的 ...

  5. _一文让你透彻理解Linux的SOCKET编程(含实例解析)

    1. 网络中进程之间如何通信 进 程通信的概念最初来源于单机系统.由于每个进程都在自己的地址范围内运行,为保证两个相互通信的进 程之间既互不干扰又协调一致工作,操作系统为进程通信提供了相应设施,如 U ...

  6. 简单理解php的socket编程

    php的socket编程算是比较难以理解的东西吧,不过,我们只要理解socket几个函数之间的关系,以及它们所扮演的角色,那么理解起来应该不是很难了,在笔者看来,socket编程,其实就是建立一个网络 ...

  7. Socket 编程实现基于 HTTP 协议的客户和服务

    目录 前言 研究背景及意义 研究内容及方法 研究要求与目标 相关知识点 HTTP协议 TCP协议 UDP协议 Socket编程技术 需求分析 Socket编程 Swing包 多线程的应用 功能设计 功 ...

  8. Telnet协议详解及使用C# 用Socket 编程来实现Telnet协议 - Atpking - 博客园

    Telnet协议详解及使用C# 用Socket 编程来实现Telnet协议 - Atpking - 博客园 Telnet协议详解及使用C# 用Socket 编程来实现Telnet协议 - Atpkin ...

  9. 通过Socket编程理解TCP三次握手

    Socket编程--应用层开发 由于传输层以下都是属于操作系统内部的服务(内部的网络管理模块) Socket就是其提供的窗口,如果你想利用系统网络管理中的传输层.网络层.链路层服务你都需要通过Sock ...

最新文章

  1. std::transform使用
  2. Windows下安装 openpyxl
  3. 有关logistic(sigmoid)函数回归
  4. python学习笔记(十一)标准库sys
  5. 卸载chrome_Chrome 浏览器必备“扩展管理工具”,一键管理 Chrome 扩展
  6. jquery获取表格中特定列
  7. Java代码内容概述
  8. Linux开机启动过程(11):start_kernel 初始化(至setup_arch解析cmdline前)
  9. Facebook 推远程办公政策,但要“调整”薪资,你觉得 OK 吗?
  10. Unity Shader 记录
  11. Mac下Android Studio快捷键
  12. 悟空学Linux专栏----第3篇
  13. 数据结构实践课程设计【通讯录管理系统】
  14. 拓端tecdat|R语言用ARIMA模型预测巧克力的兴趣趋势时间序列
  15. 5个值得安利的PC软件,建议收藏转发
  16. python实现自动打卡_python实现腾讯文档自动打卡教程
  17. 【Gem5】有关gem5模拟器的资料导航
  18. 基于FPGA的LD3320语音识别模块驱动设计
  19. 13典藏AutoHotKey脚本让您生活更轻松
  20. 大学综合测评中,使用VBA代码自动完成EXCEL成绩表

热门文章

  1. 发热门诊医疗服务监测数据上报系统
  2. 欣弗(克林霉素磷酸酯葡萄糖注射液)----恐怖的抗生素
  3. 计算机数值模拟仿真技术的优点,数值模拟的优缺点优点.ppt
  4. PM成长日记第三话-那些年我们一起做过的项目
  5. UltraISO 绿色多国语言版
  6. python中路径的表示方式
  7. WAP版手机外卖订餐系统设计与实现(含论文)SSM
  8. 商务通“隐形手机”牛皮轰轰可以休矣!
  9. UA OPTI570 量子力学23 角动量基础
  10. webpack 热加载原理探索