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

news/2024/5/18 15:59:43 标签: udp, tcp/ip, 网络, 计算机网络, java, 网络协议, 网络通信

小王学习录

  • 今日鸡汤
  • 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的服务器端代码

服务器要完成三个任务:

  • 接受来自客户端的报文段(请求)
  • 根据请求来计算响应(复杂业务逻辑)
  • 将响应发送到客户端
java">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的客户端代码

客户端要完成四个任务:

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

http://www.niftyadmin.cn/n/5133615.html

相关文章

ctfshow-web入门命令执行29

29 源代码给了禁用flag 使用tac、nl ?cecho nl f*; ?cecho tac f*; 30 多禁用了system和php 和上题区别不大,使用上一题命令就能解 ?cecho nl f*; ?cecho tac f*; 31 禁用了空格使用%09代替 ?cecho%09tac%09f*; 32 禁用了echo 使用php伪协议 ?cinclud…

怎样才是优秀的程序员?

目标 我可是要成为程序猿王的男人!! 工作 工作,学习,效率非常高。知道该做什么事情,什么事情优先级高。独立思考的能力,不盲目听从。 技术 熟悉开源技术。学习有长期价值的技术。十年后还有用的技术。…

AntDB-M的扩展功能,性能提升和热更新轻松搞定

AntDB-M的基本功能包括提供各种各样的内置函数,比如数值类型函数SUM、字符型函数STRCMP、日期时间型函数ADDDATE等,这些内置的函数给使用者提供了处理基本数据类型的能力,增强了AntDB-M的功能。 AntDB-M的内置函数作为基本功能,提…

主定理(一般式)

主定理(Master Theorem)是用于分析递归算法时间复杂度的一个重要工具。它适用于形式化定义的一类递归关系,通常采用分治策略解决问题的情况。 目录 主定理简化版的局限主定理一般形式情况1: n l o g b a n^{log_{b}{a}} nlogb​a …

HDU 1062:字符串反转

【题目来源】http://acm.hdu.edu.cn/showproblem.php?pid1062【题目描述】 Ignatius likes to write words in reverse way. Given a single line of text which is written by Ignatius, you should reverse all the words and then output them.【输入格式】 The input cont…

Android WMS——ViewRootImpl分析(六)

一、简介 ViewRootImpl是View中的最高层级,属于所有View的根(但ViewRootImpl不是View,只是实现了ViewParent接口),维护了整个视图结构,并作为输入事件的分发器和绘图管道的输入端点,承担着输入事件分发、窗口管理、视图绘制和系统事件响应等关键角色。对于Android应用程…

互联网应用架构的演进(八大架构的演进过程)

文章目录 前言常见概念八大架构演进过程单机架构应用数据分离架构应用服务集群架构读写/主从分离架构冷热分离架构垂直分库架构微服务架构容器编排架构 前言 博主最近在学中间件,理解互联网应用架构的演进过程,对于中间件的作用理解和在整体中定位十分有…

解决找不到vcruntime140.dll,无法继续执行代码方法

在计算机使用过程中,我们经常会遇到一些错误提示,其中之一就是“找不到vcruntime140.dll”。这个错误通常发生在运行某些程序或游戏时,它会导致程序无法正常启动或运行。那么,找不到vcruntime140.dll,无法继续执行代码…