基于UDP/TCP的网络通信编程实现

news2024/12/31 3:40:24

小王学习录

  • 今日鸡汤
  • Socket套接字
    • 基于UDP来实现一个网络通信程序
      • DatagramSocket类
      • DatagramPacket类
      • 基于UDP的服务器端代码
      • 基于UDP的客户端代码
    • 基于TCP来实现一个网络通信程序
      • ServerSocket类
      • Socket类
      • 基于TCP的服务器端代码
      • 基于TCP的客户端代码
      • 优化之后的服务器端代码
  • 补充
    • TCP长短连接
    • IO多路复用(多路转接)

今日鸡汤

红色是心中永不褪色的赤诚
在这里插入图片描述

Socket套接字

操作系统为网络编程提供了Socket api, Socket是基于TCP/IP协议的网络通信的基本单元, 基于Socket的网络程序开发就是网络编程.

  • 由于直接与应用层联系的是传输层, 所以针对应用层协议(TCP, UDP), Shocket提供了三种套接字, 分别是流套接字(使用TCP), 数据报套接字(使用UDP), 原始套接字
    先简单介绍一下TCP和UDP吧
  1. TCP传输有连接, 可靠传输, 面向字节流, 全双工
    (1)有连接: 在数据转发之前会先建立连接, 这里涉及到挥手, 之后会具体介绍
    (2)可靠传输: 可靠传输不代表一定会传输过去, 而是说发送方会知道是否发送成功, 如果失败, 则会重新发送
    (3)面向字节流: 以字节为单位
    (4) 全双工: 在发送的同时也可以作为接收方来接收数据
  2. UDP传输无连接, 不可靠, 面向报文段, 全双工
    (1) 无连接: 在数据转发之前发送方和接收方不会建立连接
    (2) 不可靠: 发送方在发送之后不会管是否被接受
    (3) 面向报文段: 发送数据以报文段为单位
    (4) 全双工: 在发送数据的同时可以作为接收方接受数据

基于UDP来实现一个网络通信程序

在这里要接触到两个类: DatagramSocket, 和DatagramPacket.

端口号用于指定区分进程, 因此一个端口只能同时被一个进程使用(实际上端口是被Socket对象使用), 一个进程可以同时使用多个进程(这里对端口号不熟悉有疑惑的同志可以先查阅了解一下端口号的作用)

当进程fock一个子进程时, 可以实现一个端口被多个进程使用, 但是java并没有提供fock的api

DatagramSocket类

通过DatagramSocket类创建的对象就是一个Socket, 操作系统将这个socket对象看成是一个文件, 之前普通文件对应的硬件为硬盘, 这里的socket对应的硬件是网卡, 有了socket之后就可以通过socket来操作网卡, 从而实现与其他主机的通信了.
下面看一下DatagramSocket类中的方法

  • 构造方法
    在这里插入图片描述构造方法无参时, 会为当前的通信线程随机安排一个空闲端口, 指定port参数时会为当前线程中的socket显式绑定一个端口. 通常为服务器显式指定一个端口, (因为服务器上的端口使用情况程序员是清楚的, 指定端口之后方便客户端进行访问) 客户端随机分配空闲端口(因为不确定当前哪些端口空闲)

  • 发送和接收
    在这里插入图片描述这两个方法用于客户端表示向服务器发起请求, 接受来自服务器端的响应
    这两个方法用于服务器表示接受客户端的请求, 向客户端发起响应

  • 关闭(释放资源)在这里插入图片描述

DatagramPacket类

通过DatagramPacket类创建的对象是一个数据报. UDP是面向报文段, 创建了DatagramPacket对象之后便可以使用数据报来进行通信, 下面看看这个类的方法

  • 构造方法在这里插入图片描述由构造方法可以知道, 在创建数据报时可以使用缓冲区数组, 并需要指定目的ip地址和目的端口号.注意这里的缓冲数组是一个空数组, 在接收到来自客户端的报文段时会填充, 属于输出型参数

还有一些获取当前报文段内容, 获取当前报文段中的源ip, 获取当前报文段中的源端口等就不一 一列了

基于UDP的服务器端代码

服务器要完成三个任务:

  • 接受来自客户端的报文段(请求)
  • 根据请求来计算响应(复杂业务逻辑)
  • 将响应发送到客户端
public class echoServer1 {
   
    private DatagramSocket socket = null;
    //创建pocket对象, 这里是服务器端, 需指定端口号
    public echoServer1(int port) throws SocketException {
   
        socket = new DatagramSocket(port);
    }
    public void start() throws IOException {
   
        System.out.println("服务器启动: ");
        while (true){
   
        //创建数据报, 用于接受来自客户端的数据报
            DatagramPacket requestPacket = new DatagramPacket(new byte[1024], 1024);
            //这里的receive会陷入阻塞, 直到有数据报发过来
            socket.receive(requestPacket);
            //将数据报中的内容转换为字符串, 方便计算响应
            //上面的缓冲数组不一定会填满, 这里只获取实际长度即可(getLength)
            String request = new String(requestPacket.getData(), 0, requestPacket.getLength());
            //调用计算方法, 计算响应
            String response = handle(request);
            //注意此处用response.getBytes().length, 而不用responsePacket.length(), 因为responsePacket中可能含有汉字, 汉字转换为byte类型之后字节个数与字符个数不一样
            DatagramPacket responsePacket =new DatagramPacket(response.getBytes(), response.getBytes().length,
                    requestPacket.getSocketAddress());
            //将响应发送给客户端
            socket.send(responsePacket);
            //打印日志
            System.out.printf("[%s, %d], req: %s, resp: %s \n", requestPacket.getAddress().toString(), requestPacket.getPort(),
                    request, response);
        }
    }
    public String handle(String request){
   
    //这里的响应只是简单的回显, 没有复杂的代码逻辑
        return request;
    }
 
    public static void main(String[] args) throws IOException {
   
       //创建服务器对象, 指定端口为1025, 此端口号与客户端发送请求时指定的端口号需一致
        echoServer1 server1 = new echoServer1(1025);
        //调用start方法, 启动服务器
        server1.start();
    }
}

基于UDP的客户端代码

客户端要完成四个任务:

  • 从控制台接收数据
  • 根据数据向服务器发送请求
  • 接受服务器的响应
  • 将服务器响应打印出来
public class echoClient {
   
//创建一个socket, 用于和客户端通信
    private

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

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

相关文章

RabbitMQ学习04

文章目录 发布确认1. 发布确认的原理2. 发布确认的策略2.1.开启发布确认的方法2.2.单个确认2.3.批量确认发布2.4.异步确认发布2.5.如何处理异步未确认消息2.6 总结: 发布确认 1. 发布确认的原理 生产者将信道设置成 confirm 模式,一旦信道进入 confirm …

Spring Cloud Alibaba 教程 Fegin 篇

Spring Cloud Alibaba 教程 | Feign 篇 写在前面的话&#xff1a; 本笔记在参考网上视频以及博客的基础上&#xff0c;只作为个人学习笔记&#xff0c;如有侵权联系删除&#xff0c;谢谢&#xff01; 1、Feign替代RestTemplate ​ 1.1 引入依赖 <!-- Feign 客户端依赖 --&…

StringBuffer类提供针对字符的操作方法

StringBuffer类是Java中用于操作字符串的一个类&#xff0c;提供了许多针对字符的操作方法&#xff0c;例如&#xff1a; append()&#xff1a;用于在字符串末尾添加字符或字符串。 insert()&#xff1a;用于在字符串的指定位置插入字符或字符串。 delete()&#xff1a;用于删…

Spring中简单的获取Bean对象(对象装配)

获取Bean对象也叫做对象装配&#xff0c;是把对象取出来放到某个类中&#xff0c;有时候也叫对象注入&#xff01; 对象装配&#xff08;对象注入&#xff09;更加简单的读取Bean&#xff08;是从Spring容器中读取某个对象放到当前类里面&#xff09;的实现方法有以下3种&…

06 MIT线性代数-线性无关,基和维数Independence, basis, and dimension

1. 线性无关 Independence Suppose A is m by n with m<n (more unknowns than equations) Then there are nonzero solutions to Ax0 Reason: there will be free variables! A中具有至少一个自由变量&#xff0c;那么Ax0一定具有非零解。A的列向量可以线性组合得到零向…

【AD9361 数字接口CMOS LVDSSPI】C 并行数据之LVDS

接上一部分&#xff0c;AD9361 数字接口CMOS &LVDS&SPI 目录 一、LVDS模式数据路径和时钟信号LVDS模式数据通路信号[1] DATA_CLK[2] FB_CLK[3] Rx_FRAME[4] Rx_D[5&#xff1a;0][5] Tx_FRAME[6]Tx_D[5&#xff1a;0][7] ENABLE[8] TXNRX系列 二、LVDS最大时钟速率和信…

附录B 其他第三方软件移植(FTP、OpenSSH、GDB)

目录 开发板 FTP 服务器移植与搭建vsftpd 源码下载vsftpd 移植vsftpd 服务器测试配置vsftpd添加新用户Filezilla 连接测试 开发板 OpenSSH 移植与使用OpenSSH 简介OpenSSH 移植OpenSSH 源码获取移植zlib 库移植openssl 库移植openssh 库 openssh 设置openssh 使用ssh 登录scp 命…

opencv4.x通过cmake编译带cuda

首选确定目标&#xff0c;需要编译的是opencv4.5.5带第三方库&#xff0c;带cuda的版本&#xff0c;使用vs编译器&#xff0c;编译releasedebug版本。 需要先安装好cmake cuda cudnn等基础依赖&#xff0c;并且确保安装好vs的编译器&#xff0c;并且大小版本都符合实际要求。 …

【C++的OpenCV】第十四课-OpenCV基础强化(三):Mat元素的访问之data和step属性

&#x1f389;&#x1f389;&#x1f389; 欢迎来到小白 p i a o 的学习空间&#xff01; \color{red}{欢迎来到小白piao的学习空间&#xff01;} 欢迎来到小白piao的学习空间&#xff01;&#x1f389;&#x1f389;&#x1f389; &#x1f496; C\Python所有的入门技术皆在 我…

信息系统项目管理师教程 第四版【第4章-信息系统管理-思维导图】

信息系统项目管理师教程 第四版【第4章-信息系统管理-思维导图】

由一个单例模式引发的思考-holder类方式

前言&#xff1a; 最近在看《Java并发编程实践》&#xff0c;里面提到了一种实现单例模式的方式&#xff0c;并大致说明了机制&#xff0c;但仍不是很清晰&#xff0c;今日有空&#xff0c;查阅相关书籍&#xff0c;尝试解释其中道理。 单例模式&#xff1a; 单例模式是一种常…

队列(8.6)

目录 2.队列 2.1队列的概念及结构 2.2队列的实现 2.2.1初始化队列 2.2.2队尾入队列 2.2.3队头出队列 2.2.4获取队列头部元素 2.2.5 销毁队列 3.栈和队列面试题 225. 用队列实现栈 - 力扣&#xff08;LeetCode&#xff09; 232. 用栈实现队列 - 力扣&#xff08;LeetC…

【送书福利-第二十一期】《ChatGPT进阶:提示工程入门》

&#x1f60e; 作者介绍&#xff1a;我是程序员洲洲&#xff0c;一个热爱写作的非著名程序员。CSDN全栈优质领域创作者、华为云博客社区云享专家、阿里云博客社区专家博主、前后端开发、人工智能研究生。公粽号&#xff1a;程序员洲洲。 &#x1f388; 本文专栏&#xff1a;本文…

正点原子嵌入式linux驱动开发——Linux 多点电容触摸屏

随着智能手机的发展&#xff0c;电容触摸屏也得到了飞速的发展。相比电阻触摸屏&#xff0c;电容触摸屏有很多的优势&#xff0c;比如支持多点触控、不需要按压&#xff0c;只需要轻轻触摸就有反应。ALIENTEK的三款RGB LCD屏幕都支持多点电容触摸&#xff0c;本章就以ATK7016这…

Spring Cloud Alibaba Seata 实现 SAGA 事物

Seata 是一款开源的分布式事务解决方案&#xff0c;致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式&#xff0c;为用户打造一站式的分布式解决方案 Seata 官网&#xff1a;https://seata.io/zh-cn/ Spring Cloud Alibaba 官…

【Java网络原理】 六

本文主要介绍了网络层的IP协议/NAT机制/IPv6的由来以及在数据链路层涉及到的以太网协议和DNS域名解析系统 一.网络层 1.IP协议 各个字段所表示的含义 >4位版本号 用来表示IP协议的版本&#xff0c;现在只有两个版本IPv4 &#xff0c;IPv6 >4位首部长度 IP报头可变&…

【自然语言处理】【长文本处理】RMT:能处理长度超过一百万token的Transformer

相关博客 【自然语言处理】【长文本处理】RMT&#xff1a;能处理长度超过一百万token的Transformer 【自然语言处理】【大模型】MPT模型结构源码解析(单机版) 【自然语言处理】【大模型】ChatGLM-6B模型结构代码解析(单机版) 【自然语言处理】【大模型】BLOOM模型结构源码解析(…

AI直播换脸——DeepFaceLab 3.0模型训练与微调

前言 DeepFaceLab是一种基于深度学习的人脸合成和转换工具。它使用了深度神经网络来分析和修改图像中的人脸部分&#xff0c;可以实现将一个人的脸部特征应用到另一个人的照片上&#xff0c;或者进行面部表情、年龄、性别等特征的变换。 DeepFaceLab具备一系列核心功能&#x…

Matplotlib详解(plt 和ax分别是什么)

Matplotlib中的plt 和 ax 分别是什么&#xff1f; 概念引入两种绘图方式的区别subplot 绘制Matplotlib 常见组件设置整理4.1 设置显示中文字体4.2 设置标题4.3 边框的显示问题4.4 图例设置&#xff08;legend&#xff09;4.5 图形与边框之间的留白控制4.6 设置双坐标轴4.7 坐标…

Java毕业设计 SpringBoot 新能源充电桩管理系统

Java毕业设计 SpringBoot 新能源充电桩管理系统 SpringBoot 新能源充电桩管理系统 功能介绍 管理员 登录 验证码 注册 系统用户管理 普通用户管理 通知公告管理 留言管理 充电站管理 充电桩管理 充电桩预约 充电管理 订单管理 修改密码 普通用户 登录 修改个人资料 通知公告…