通信基石Socket结合OOP实现程序间的通信

news2024/10/7 2:29:37

学习目录

  • 前言
    • 一.Socket是用来干什么的
    • 二.如何用代码建立通信连接
    • 三.Java实现TCP发收消息
    • 四.UDP的Socket编程

前言

先分享一下最近看到的几篇面经:
在这里插入图片描述
看了一下关于Socket的知识点好像面试十分高频,它作为通信的基石许多组件,框架都是在他的基础之上进行封装,确实有必要深入了解一下
特别是网络编程结合I/O操作来要求你实现一个网络聊天室,如果面试官突然问到你 你能娓娓道来吗?

今天主要针对Socket展开

一.Socket是用来干什么的

首先
标识每个端点IP地址和端口号称为套接字。socket={IP:PORT}。标识源IP地址,源port,目的IP 地址,目的port,协议统称为套接字对。套接字(socket)是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。
套接字(socket)是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口。
一个Socket是一对IP地址和端口。
在这里插入图片描述

Socket可以看成在两个程序进行通讯连接中的一个端点,一个程序将一段信息写入Socket中,该Socket将这段信息发送给另外一个Socket中,使这段信息能传送到其他程序中。
你可以这么理解:socket是进程之间用来对话的中间层工具。信息的传递需要Socket为我们架起桥梁!

二.如何用代码建立通信连接

站在面向对象的肩膀之上,设计者已经在java.net包中封装了用于通信连接的类与接口ServerSocket与Socket,只需要指定端口就能进行简单的连接
在这里插入图片描述
这是不是在你学JavaWeb里的Servlet中似曾相识呢?
可以发现,通过Socket我成功地将两个程序(两个对象)串联了起来,而通信的秘密就蕴藏在其中,因为通过两端的Socket对象可以进行I/O操作,从而实现各式各样的通信!
注意当客户端连接到服务端后,实际上客户端也是通过一个端口和服务端进行通讯的,这个端口是TCP/IP来分配的,是不确定的,是随机的
在这里插入图片描述

三.Java实现TCP发收消息

前面说过,支持TCP/IP协议的网络通信的基本操作单元
TCP讲究准确安全(三次握手,四次挥手),他是基于连接的!
写两个Java类来仿照客户端与服务器端之间基于TCP的消息收发
客户端从本地发送一张图片到服务器端,服务器端接收并保持到指定位置,并回送消息,客户端显示收到消息
在这里插入图片描述
通信的本质就是以Socket通道为对象来做I/O操作
客户端:
面向指定端口的Socket编程

public class Client {
    public static void main(String[] args) throws Exception {
        //客户端通过主机连接服务器9999 端口
        InetAddress inet = InetAddress.getLocalHost();
        Socket socket = new Socket(inet, 9999);
        //指定文件路径
        String filePath = "D:\\5.jpg";
        //将图片以文件流的形式传输到通道中
        BufferedInputStream bio = new BufferedInputStream(new FileInputStream(filePath));
        //通过工具类将流数据转成字节数组
        byte[] bytes = StreamUtils.streamToByteArray(bio);

        //将数据写入socket通道
        OutputStream outputStream = socket.getOutputStream();
        outputStream.write(bytes);

        socket.shutdownOutput();

        //接收服务端回送的消息
        InputStream inputStream = socket.getInputStream();
        String s = StreamUtils.streamToString(inputStream);
        System.out.println(s);
        //关流
        bio.close();
        inputStream.close();
        socket.close();
    }
}

服务器端:
面向返回的Socket编程

public class Server {
    public static void main(String[] args) throws Exception {
        //指定连接的端口号
        ServerSocket serverSocket = new ServerSocket(9999);
        //得到连接后返回的socket对象
        Socket accept = serverSocket.accept();
        //通过对象得到输入流
        InputStream inputStream = accept.getInputStream();
        //将输入流写到字符输入流
        BufferedInputStream bis = new BufferedInputStream(inputStream);
        //通过工具类将字符输入流对象转成字节数组
        byte[] bytes = StreamUtils.streamToByteArray(bis);
        String path = "src\\mysqlSend.png";
        //创建输出流对象,将转成字节数组的文件流输出到指定目录
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(path));
        bos.write(bytes);
        bos.flush();//刷新
            
        //向客户端发送收到图片
        BufferedWriter osw = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream()));
        osw.write("收到图片");
        osw.flush();
        accept.shutdownOutput();//设置结束标记
            
        accept.close();
        osw.close();
        serverSocket.close();
        bos.close();
    }
}

可以看到,这一切操作的基础都是在以循环往复的Socket通道为对象进行,所以强调TCP是基于连接的!

四.UDP的Socket编程

而UDP与之相反,他是不基于连接的!所以应用场景十分少。
在B站上看到过这样一句话非常生动形象:

UDP协议就相当于是写信给对方,寄出去信件之后不能知道对方是否收到信件,信件内容是否完整,也不能得到及时反馈。
TCP协议就像是打电话通信,在这一系列流程都能得到及时反馈,并能确保对方及时接收到。

在这里插入图片描述
UDP的宗旨:
使用UDP协议进行数据传输是,需要将需要传输数据定义为数据报(DatagramPaket),在数据报中指明数据所要到达Socket(主机地址和端口号),然后再将数据报发送出去。明白了这个再来结合I/O不是有手就行啊

一个UDP通信小Demo:
客户端:

public class UDPSenderB {
    public static void main(String[] args) throws IOException {

        //1.创建 DatagramSocket 对象,准备在9998端口 接收数据
        DatagramSocket socket = new DatagramSocket(9998);

        //2. 将需要发送的数据,封装到 DatagramPacket对象
        byte[] data = "hello world!".getBytes(); //

        //说明: 封装的 DatagramPacket对象 data 内容字节数组 , data.length , 主机(IP) , 端口
        DatagramPacket packet =
                new DatagramPacket(data, data.length, InetAddress.getByName("192.168.235.128"), 9999);

        socket.send(packet);
        //构建一个 DatagramPacket 对象,准备接收数据
        // 一个数据包最大 64k
        byte[] buf = new byte[1024];
        packet = new DatagramPacket(buf, buf.length);
        //调用 接收方法, 将通过网络传输的 DatagramPacket 对象
        //填充到 packet对象
        socket.receive(packet);
        //可以把packet 进行拆包,取出数据,并显示.
        int length = packet.getLength();//实际接收到的数据字节长度
        data = packet.getData();//接收到数据
        String s = new String(data, 0, length);
        System.out.println(s);
        //关闭资源
        socket.close();
    }
}

服务器端:

public class UDPReceiverA {
    public static void main(String[] args) throws IOException {
        //1. 创建一个 DatagramSocket 对象,准备在9999接收数据
        DatagramSocket socket = new DatagramSocket(9999);
        //2. 构建一个 DatagramPacket 对象,准备接收数据
        //  一个数据包最大 64k
        byte[] buf = new byte[1024];
        DatagramPacket packet = new DatagramPacket(buf, buf.length);
        //3. 调用 接收方法, 将通过网络传输的 DatagramPacket 对象
        //   填充到 packet对象
        System.out.println("A 等待接收数据..");
        socket.receive(packet);

        //4. 可以把packet 进行拆包,取出数据,并显示.
        int length = packet.getLength();//实际接收到的数据字节长度
        byte[] data = packet.getData();//接收到数据
        String s = new String(data, 0, length);
        System.out.println(s);
        //===回复信息给B端
        //将需要发送的数据,封装到 DatagramPacket对象
        data = "Hello,Java!".getBytes();
        //说明: 封装的 DatagramPacket对象 data 内容字节数组 , data.length , 主机(IP) , 端口
        packet =
                new DatagramPacket(data, data.length, InetAddress.getByName("192.168.235.128"), 9998);
        socket.send(packet);//发送
        //5. 关闭资源
        socket.close();
    }
}

UDP通信不可靠,少用,了解就行~
文章最后,分享一点脍炙人口的八股文:

UDP协议是一种对等通信的实现,发送方只需要接受方的IP(地址)和Port(端口),就可以直接向它发送数据,不需要线连接。每个程序都可以作为服务器,也可以作为客户端。UDP是一种无连接的传输协议,每个数据报的大小限定在64KB以内。数据报是一个在网络上发送的独立信息,它的到达。到达时间以及内容本身等都不能得到保证。这种传输方式是无序的,也不能确保绝对的安全可靠,但它很简单也具有较高的效率。
使用UDP协议进行数据传输是,需要将需要传输数据定义为数据报(DatagramPaket),在数据报中指明数据所要到达Socket(主机地址和端口号),然后再将数据报发送出去。实例化DatagramPacket时使用参数port和没有使用参数port的区别在与,提供port的一方可以让别人主动发送消息过来,而没有参数port的则会在发送消息时自动绑定一个本地没有使用的端口。在接收到发送的数据报(DatagramPaket)时,不仅可以获取数据,还可以获得发送方的IP和Port,这样就可以向发送方发送数据,因此,本质上二者是对等的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/28099.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

oracle数据库id字段自增长

mysql数据库中建表的时候可以设置id字段自增长,oracle数据库中要实现id字段自增长需要借助于sequence(序列)和trigger(触发器)。 下面通过一个简单的示范说明。 --1.新建一个账户表 account create table accout( …

机械转码日记【25】多态

目录 前言 1.多态的概念 2. 多态的定义及实现 2.1多态的构成条件 2.2 虚函数 2.3虚函数的重写 2.4虚函数重写的两个例外 2.4 C11 override 和 final 2.5 重载、覆盖(重写)、隐藏(重定义)的对比 3.抽象类 3.1概念 3.2 接口继承和实现继承 4.多态的原理 4.1虚函…

个人微信api

我们是一家专业服务企业数字化微信管理服务的技术服务团队,服务于需求SCRM、机器人、营销系统、社群小助手等具有研发能力的企业,同时我们也接收因使用Xp方案、ipad方案、PC方案导致被批量封号的企业,我们合作伙伴目前包含:金融服务行业Top10…

无协同资源创新打法,这几个品牌在双11「品牌嘉年华」实现品效双收

抖音双11好物节圆满收官,每年双11,我们关注的不仅仅是不断刷新的成绩,也是在更多元的场景、更丰厚的资源和更强劲的平台资源助力之下,商家在营销动作上带来了怎样的“惊喜”。 在「内容场景」,双11期间,抖…

VScode设置pretty-printer无效

文章目录VScode设置pretty-printer无效问题解决尝试正式解决参考VScode设置pretty-printer无效 问题 win10系统下,VScode中即使在launch.json中进行了如下设置,还是无效 {"description": "为 gdb 启用整齐打印","text"…

【设计模式】 - 结构型模式 - 外观模式

目录标题前言外观模式概述结构实现:智能家电控制优缺点前言 结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者釆用组合或聚合来组合对象。 由于组合关系或聚…

基于机器学习的自动音乐生成播放器

目录 详细设计说明书 1 1 引言 1 1.1 编写目的 1 1.2 背景 1 2. 此项目的任务提出者:西电软件工程课程组、西电软件开发小组 1 1.3 定义 2 1.4 参考资料 2 3 程序描述 4 3.1 011 参数调整模块 4 3.1.3 界面设计 4 3.1.4 参数调整的内部逻辑 5 3.2 012 自动谱曲模块 …

webpack 的基本使用(详解)

前言: 你是否也是只会运用框架中集成好的Webpack配置呢?你明白每一项的意义么?你懂多少Webpack的个性化配置项呢?本篇文章为你讲解Webpack中的各种配置项参数及作用! 目录前言:一,什么是Webpack…

【算法手札】深入理解宽度遍历(bfs)和深度遍历(dfs)搜索

算法的重要性不言而喻,现在我们的生活也已经离不开各种算法,一个好的算法能大大提高程序的运行效率,是学习编程的一个重要模块,而遍历算法也是算法里的一个大的模块,今天我们一起来学习一下深度遍历算法(de…

2023最新SSM计算机毕业设计选题大全(附源码+LW)之java电子书店管理系统ya226

做毕业设计一定要选好题目。毕设想简单,其实很简单。这里给几点建议: 1:首先,学会收集整理,年年专业都一样,岁岁毕业人不同。很多人在做毕业设计的时候,都犯了一个错误,那就是不借鉴…

双功能接头试剂知识分享:Alkyne maleimide,Mal-Alkyne,炔烃-马来酰亚胺

炔烃马来酰亚胺是一种双功能接头试剂,可将末端炔烃连接到各种含硫醇分子,例如含有半胱氨酸残基的蛋白质。然后可以通过铜催化的点击化学反应将炔烃部分与各种叠氮化物缀合。 Alkyne maleimide is a bifunctional connector reagent that can connect ter…

AB Test实验设计

1. 版本设计 实验版本的设计要遵循变量的单一性,不能一下子改变多个因素,如同一个按钮不能同时改变按钮颜色和按钮文字,实验设计越简单越容易得出正确的结论。 案例时间: 2. 实验时长 业界的实验时长一般是2-3周,最…

Packet Tracer - 在 OSPFv2 中传播默认路由

地址分配表 设备 接口 IPv4 地址 子网掩码 默认网关 R1 G0/0 172.16.1.1 255.255.255.0 不适用 S0/0/0 172.16.3.1 255.255.255.252 不适用 S0/0/1 192.168.10.5 255.255.255.252 不适用 R2 G0/0 172.16.2.1 255.255.255.0 不适用 S0/0/0 172.16.3.2 …

Redis对象及redisObject源码解析

写在前面 以下内容是基于Redis 6.2.6 版本整理总结 一、对象 前面几篇文章,我们介绍了Redis用到的主要的数据结构,如:sds、list、dict、ziplist、skiplist、inset等。 但是,Redis并没有直接使用这些数据结构来实现key-value数…

使用k8s创建一个支持ssh的pod,docker

在容器场景下 用ssh去登录一个docker 是不提倡的 可是有时为了方便定位问题 我制作了一个支持ssh的镜像 节约大家的时间 docker使用方法: docker run --namec7-sshd --privileged -itd -p 1022:22 lnwaycool/centos7_ssh:v1 /usr/sbin/init ssh root127.0.0.1 -p 1022 登…

猴子也能学会的jQuery第七期——jQuery动画(上)

📚系列文章—目录🔥 猴子也能学会的jQuery第一期——什么是jQuery 猴子也能学会的jQuery第二期——引用jQuery 猴子也能学会的jQuery第三期——使用jQuery 猴子也能学会的jQuery第四期——jQuery选择器大全 猴子也能学会的jQuery第五期——jQuery样式操作…

外部H5页面打开微信小程序最新流程

当前时间2022年11月22日,记录一下外部H5如何打开指定微信小程序的指定页面最新流程。 因为微信小程序后台已关闭生成 小程序 scheme 码 入口,所以只能通过如下方式: 1.服务端获取微信小程序 scheme 码 前提条件:目前仅针对国内…

基于中国新能源汽车税收政策下成都市场发展路线研究

目 录 摘 要 I Abstract II 第一章 绪论 1 1.1选题背景及意义 1 1.2国内外新能源汽车税收政策现状 2 1.2.1国内新能源汽车税收政策 2 1.2.2国外新能源汽车税收政策 3 1.3本课题研究主要内容 4 第二章 新能源汽车市场发展现状及存在的问题 5 2.1市场发展现状 5 2.2存在的问题 5 …

TensorFlow之文本分类算法-2

1 前言 2 收集数据 3 探索数据 4 选择模型 5 准备数据 数据被输入模型之前,需要将数据转换成模型能理解的格式,该过程被称之为数据标准化。 首先,已收集到的数据样本可能是以指定的顺序存储,而在实际分析中,期望…

邮件助手、监控邮件上报电脑截图、网课监控助手

起因:看到别的网友写的一个程序,监控在家上网课的状态,防止孩子玩游戏。没界面无法配置更多参数。自己写了一个。功能基本齐全了。 收件地址:接收邮件的邮箱 抄送地址:可以多个邮箱,用|分开即可。 标题、内容、版权位置可以自定义内容。 设置发送频率(默认10分钟),…