【Java网络编程】TCP通信(Socket 与 ServerSocket)和UDP通信的三种数据传输方式

news2024/9/23 13:19:35

目录

1、TCP通信

1.1、Socket 和 ServerSocket

1.3、TCP通信示例

2、UDP的三种通信(数据传输)方式

1、TCP通信

TCP通信协议是一种可靠的网络协议,它在通信的两端各建立一个Socket对象

        通信之前要保证连接已经建立(注意TCP是一定要建立连接的)

        TCP是通过Socket产生I0流来进行网络通信的,所以发送端和接收端的两个流的方向是不一样的,比如客户端和服务器进行通信(通信前要确保建立了连接),然后客户端向服务器发送了“你好帅”,这一次发送数据的过程,它们流的方向是不一样的,针对客户端来说,它是往外发所以用的是输出流,而针对服务器来说,它是接收数据所以用的是输入流。

1.1、Socket 和 ServerSocket

        socket可以使一个应用从网络中读取和写入数据,不同计算机上的两个应用可以通过连接发送和接受字节流,当发送消息时,你需要知道对方的ip和端口,在java中,socket指的是java.net.Socket类。

        一旦成功创建一个Socket类的实例,可以用它来发送和接收字节流,发送时调用getOutputStream方法获取一个java.io.OutputStream对象,接收远程对象发送来的信息可以调用getInputStream方法来返回一个java.io.InputStream对象。

        Socket类代表一个客户端套接字,即任何时候连接到一个远程服务器应用时构建所需的socket。现在,要实现一个服务器应用,需要不同的做法。服务器需随时待命,因为不知道客户端什么时候会发来请求,此时,我们需要使用ServerSocket,对应的是java.net.ServerSocket类。 
  ServerSocket与Socket不同,ServerSocket是等待客户端的请求,一旦获得一个连接请求,就创建一个Socket示例来与客户端进行通信。 

1.3、TCP通信示例

(1)写TCP通信的步骤:

客户端:

        创建客户端的Socket对象(Socket)与指定服务端连接:Socket(string host,int port)--host为服务器ip地址,port为端口

获取输出流,写数据:OutputStream getoutputstream()

释放资源:void close()

服务器:

创建服务器端的Socket对象(ServerSocket):Serversocket(int port)

监听客户端连接,返回一个Socket对象:Socket accept()

获取输入流,读数据,并把数据显示在控制台:InputStream getInputStream()

释放资源:void close()

示例:

提示:在客户端创建了Socket对象的同时会去连接服务端,如果连接不上,代码会报错;用来通信的I0流可以关可不关,因为这个流是TCP连接通道里的流,关闭TCP连接通道时这个流自然就关了

客户端代码

public class Client {
    public static void main(String[] args) throws IOException {
        //TCP协议,发送数据
        // 1.创建Socket对象
        // 提示:在创建对象的同时会连接服务端,如果连接不上,代码会报错
        Socket socket = new Socket("127.0.0.1",10001);
        //2.可以从连接通道中获取输出流(OutputStream是引用型数据类型)
        OutputStream os = socket.getOutputStream();
        //写出数据
        //os.write("aaa".getBytes());
        os.write("你好aaa是吧".getBytes());
        //3.释放资源
        os.close();//这里的流可以关可不关,因为这个流是TCP连接通道里的流,关闭TCP连接通道时这个流自然就关了
        socket.close();
    }
}

服务器代码

public class Server {
    public static void main(String[] args) throws IOException {
        //TCP协议,接收数据
        // 1.创建对象ServerSocket
        ServerSocket ss = new ServerSocket(10001);
        //2.监听客户端的链接
        Socket socket = ss.accept();
        //3.从连接通道中获取输入流读取数据
        InputStreamReader br = new InputStreamReader(socket.getInputStream());//这时候才能正确的读取到中文数据
        int b;
        while ((b = br.read()) != -1) {
            System.out.print((char) b);
        }
        //4.释放资源
        br.close();//这里的流可以关可不关,因为这个流是TCP连接通道里的流,关闭TCP连接通道时这个流自然就关了
        ss.close();
    }
}

先运行服务器,再运行客户端

结果结果

(2)客户端不断发送消息

客户端代码

public class Client {
    public static void main(String[] args) throws IOException {
        //客户端:多次发送数据
        //服务器:接收多次接收数据,并打印
        //1.创建Socket对象
        Socket socket = new Socket("127.0.0.1",10001);
        //2.可以从连接通道中获取输出流(OutputStream是引用型数据类型)
        OutputStream os = socket.getOutputStream();
        Scanner sc = new Scanner(System.in);
        while (true) {
            System.out.println("输入要发送的数据:");
            String str = sc.nextLine();
            if ("886".equals(str)) {
                break;
            }
            //写出数据
            os.write(str.getBytes());
        }
        //3.释放资源
        socket.close();
    }
}

服务器代码

public class Server {
    public static void main(String[] args) throws IOException {
        //客户端:多次发送数据
        //服务器:接收多次接收数据,并打印
        // 1.创建对象ServerSocket
        ServerSocket ss = new ServerSocket(10001);
        //2.监听客户端的链接
        Socket socket = ss.accept();
        //3.从连接通道中获取输入流读取数据
        InputStreamReader br = new InputStreamReader(socket.getInputStream());
        int b;
        while ((b = br.read()) != -1) {
            System.out.print((char) b);
        }
        //4.释放资源
        ss.close();
    }
}

运行结果:客户端发送886后结束通信

(3)客户端和服务器互发互收消息

//客户端代码
public class Client {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1",10001);
        OutputStream os = socket.getOutputStream();
        String str = "你看的到我发信息吗?";
        os.write(str.getBytes());
        //往服务器写出结束标记,shutdownOutput()是关闭输出流,如果不关闭,服务器那边的输入流就不会关闭,就会继续阻塞在读信息的过程中
        socket.shutdownOutput();

        InputStreamReader br = new InputStreamReader(socket.getInputStream());
        int b;
        while ((b = br.read()) != -1) {
            System.out.print((char) b);
        }
        socket.close();
    }
}



//服务器代码
public class Server {
    public static void main(String[] args) throws IOException {
        ServerSocket ss = new ServerSocket(10001);
        Socket socket = ss.accept();
        InputStreamReader br = new InputStreamReader(socket.getInputStream());
        int b;
        while ((b = br.read()) != -1) {
            System.out.print((char) b);
        }
        socket.getOutputStream().write("是的,我看到了。".getBytes());//链式编程
        //写出结束标记,shutdownOutput()是关闭输出流
        socket.shutdownOutput();
        socket.close();
        ss.close();
    }
}

运行结果

服务器端:

客户端:

2、UDP的三种通信(数据传输)方式

Java网络编程中的UDP(User Datagram Protocol)通信编程支持单播、组播和广播这三种方式。

  • 单播(Unicast):单播是指将数据从一个发送者发送到一个接收者的传输方式。在UDP编程中,通过指定目标主机的IP地址和端口号,可以实现单播通信。
  • 组播(Multicast):组播是指将数据从一个发送者发送到一组特定的接收者的传输方式。在UDP编程中,可以使用Java的MulticastSocket类来支持组播通信。
  • 广播(Broadcast):广播是指将数据从一个发送者发送到网络中的所有设备的传输方式。在UDP编程中,可以通过指定广播地址(通常是特定的子网地址)来实现广播通信。

单播:前面的发送接收数据的通信方式就是单播

组播:组播地址:224.0.0.0~239.255.255.255;其中224.0.0.0~224.0.0.255为预留的组播地址

广播:广播地址:255.255.255.255

UDP组播示例:

//发送端代码
public class SendMessageDemo {
    public static void main(String[] args) throws IOException {
        //组播发送端代码
        // 创建MulticastSocket对象
        MulticastSocket ms = new MulticastSocket();
        String str = "你好,你好!";
        byte[] bytes = str.getBytes();
        InetAddress address = InetAddress.getByName("224.0.0.2");//这里设置的ip为组播地址
        int port = 10000;
        DatagramPacket dp = new DatagramPacket(bytes, bytes.length,address,port);
        //调用MulticastSocket发送数据方法发送数据
        ms.send(dp);
        //释放资源
        ms.close();
    }
}



//接收端代码
public class ReceiveMessageDemo1 {
    public static void main(String[] args) throws IOException {
        //1.创建MulticastSocket对象,并且设置端口为10000
        MulticastSocket ms = new MulticastSocket(10000);
        //2.将将当前本机,添加到224.0.0.1的这一组当中
        InetAddress address = InetAddress.getByName("224.0.0.2");
        ms.joinGroup(address);

        byte[] bytes = new byte[1024];
        DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
        //接收数据包
        ms.receive(dp);
        //3.解析数据包
        byte[] data = dp.getData();//获取数据包dp中的数据
        int len = dp.getLength();//获取这次收到了多少个字节的数据
        String str = new String(data,0,len);
        //因为字节数组data的长度是1024,太大了,所以要用到这次收到了多少个字节的数据个数len来决定把字节数组data中的多少数据转换成字符串
        String ip = dp.getAddress().getHostAddress();//ip
        String name = dp.getAddress().getHostName();//主机名

        System.out.println("ip为:" + ip + ",主机名为:" + name + "的人,发送了数据:" + str);
        //释放资源
        ms.close();
    }
}

要想运行并验证这个示例,修要允许运行多个发送端,步骤如下:

完成这些操作后,多运行几个接收端就可以了

发送端运行结果

接收端1显示结果

接收端2显示结果

UDP广播示例:

发送端把目的主机的IP设置为:255.255.255.255,这就是广播了

public class SendMessageDemo {
    public static void main(String[] args) throws IOException {
        /*
        按照下面的要求实现程序
        UDP发送数据:数据来自于键盘录入,直到输入的数据是886,发送数据结束
        UDP接收数据:因为接收端不知道发送端什么时候停止发送,故采用死循环接收
         */
        //1.创建对象DatagramSocket的对象
        DatagramSocket ds = new DatagramSocket();
        Scanner sc = new Scanner(System.in);
        while (true) {
            System.out.println("请输入你想说的话:");
            String str = sc.next();
            byte[] bytes = str.getBytes();
            //InetAddress address = InetAddress.getByName("127.0.0.1");//设置目标主机的IP为:127.0.0.1,这是单播方式
            InetAddress address = InetAddress.getByName("255.255.255.255");//设置目标主机的IP为:255.255.255.255,这是广播方式
            int port = 10086;//设发送到目标主机的10086端口
            //2.打包数据
            DatagramPacket dp = new DatagramPacket(bytes, bytes.length, address, port);
            //3.发送数据
            ds.send(dp);
            if ("886".equals(str)) {//如果输入的数据是886,发送数据结束
                break;
            }
        }
        //4.释放资源
        ds.close();
    }
}

推荐:

【Java网络编程】网络编程概述、UDP通信(DatagramPacket 与 DatagramSocket)-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/m0_65277261/article/details/137928825?spm=1001.2014.3001.5501

【java多线程】线程池 ThreadPoolExecutor类和Executors工厂类以及线程池的最优大小_threadpool 线程池工厂类-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/m0_65277261/article/details/137673188?spm=1001.2014.3001.5501

【Spring】依赖注入(DI)时常用的注解@Autowired和@Value-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/m0_65277261/article/details/137784706?spm=1001.2014.3001.5501

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

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

相关文章

从win10升级到win11后,安全中心没有病毒防护的解决办法

从win10升级到win11后,安全中心没有病毒防护的解决办法 问题就是Win11的安全中心打开没有病毒和威胁防护选项(不装其它第三方防病毒软件的情况下)。 这可能是因为注册表出了问题。 具体操作如下: 点击Windows左下角搜索栏&…

使用JavaScript及HTML、CSS完成秒表计时器

案例要求 1.界面为一个显示计时面板和三个按钮分别为:开始&#xff0c;暂停&#xff0c;重置 2.点击开始&#xff0c;面板开始计时&#xff0c; 3.点击暂停&#xff0c;面板停止 4.点击重置&#xff0c;计时面板重新为0 案例源码 <!DOCTYPE html> <html lang"…

echart-better基于最新的echarts5.5标题旋转功能

使用教程以及相关的echarts-better最新的包在这里&#xff1a;https://edu.csdn.net/course/detail/24569 echarts在侧边竖向展示标题&#xff0c;以及次标题 主标题和次标题进行旋转&#xff0c;适用于移动端或其他场景。

Azure AD统一认证及用户数据同步开发指导

本文主要目的为&#xff1a;指导开发者进行自有服务与Azure AD统一认证的集成&#xff0c;以及阐述云端用户数据同步的实现方案。本文除了会介绍必要的概念、原理、流程外&#xff0c;还会包含Azure门户设置说明&#xff0c;以及使用Fiddler进行全流程的实操验证&#xff0c;同…

.net core webapi 添加日志管理看板LogDashboard

.net core webapi 添加日志管理看板LogDashboard 添加权限管理&#xff1a; 我们用的是Nlog文件来配置 <?xml version"1.0" encoding"utf-8" ?> <nlog xmlns"http://www.nlog-project.org/schemas/NLog.xsd"xmlns:xsi"http:/…

CSS基础:浮动(float)的3种方式,清除浮动3种方式的详解

你好&#xff0c;我是云桃桃。 一个希望帮助更多朋友快速入门 WEB 前端的程序媛。 云桃桃-大专生&#xff0c;一枚程序媛&#xff0c;感谢关注。回复 “前端基础题”&#xff0c;可免费获得前端基础 100 题汇总&#xff0c;回复 “前端工具”&#xff0c;可获取 Web 开发工具合…

iOS - Runloop在实际开发中的应用

文章目录 iOS - Runloop在实际开发中的应用1. 控制线程生命周期&#xff08;线程保活&#xff09;2. 解决NSTimer在滑动时停止工作的问题2.1. 案例2.2 解决 3. 监控应用卡顿4. 性能优化 iOS - Runloop在实际开发中的应用 1. 控制线程生命周期&#xff08;线程保活&#xff09;…

linux系统安全与应用【下】

目录 1.开关机安全控制 1.1GRUB限制 2.终端登录安全控制 2.1 限制root只在安全终端登录 2.2 禁止普通用户登录 3.弱口令检测 3.1 Joth the Ripper&#xff08;JR&#xff09; 4.网络端口扫描 4.1 nmap命令 1.开关机安全控制 1.1GRUB限制 通常情况下在系统开机进入GRU…

Java微服务架构之Spring Boot —上篇

SpringBoot 概述 SpringBoot提供了一种快速使用Spring的方式&#xff0c;基于约定优于配置的思想&#xff0c;可以让开发人员不必在配置与逻辑业务之间进行思维的切换&#xff0c;全身心的投入到逻辑业务的代码编写中&#xff0c;从而大大提高了开发的效率&#xff0c;一定程度…

模板初阶

泛型编程&#xff1a; 泛型编程&#xff1a;编写与类型无关的通用代码&#xff0c;模板是泛型编程的基础 class Test { public:void Swap(int& left, int& right){int tmp left;left right;right tmp;}void Swap(double& left, double& right){double tmp…

orbslam2+kitti数据集序列图像

文章目录 一、下载ORB Slam2依赖二、安装编译ORB_SLAM2三 、运行Kitee数据集3.1 数据集准备3.2 启动&#xff01;&#xff01;&#xff01; 安装ORB Slam2遇到的问题总结参考资料 一、下载ORB Slam2依赖 Orb Slam2 需要下载的依赖项&#xff1a; Pangolin0.5 、Eigen3.1以上、…

【Hadoop3.3.6】数据块副本放置策略及解析EditLog和FsImage

目录 一、摘要二、正文2.1 环境说明2.2 网络拓扑2.3 Hadoop副本放置策略介绍2.4 解析EditLog和Fsimage镜像文件三、小结一、摘要 通过解析存储于NameNode节点上的日志文件EditLog和镜像文件(元数据)Fsimage来反向验证HDFS的数据块副本存放策略,其目的是希望加深对Hadoop的数…

AJAX——同步代码和异步代码

1.同步代码 同步代码&#xff1a;浏览器是按照我们书写代码的顺序一行一行地执行程序的。浏览器会等待代码的解析和工作&#xff0c;在上一行完成后才会执行下一行。这样做是很有必要的&#xff0c;因为每一行新的代码都是建立在前面代码的基础之上的。 这也使得它成为一个同步…

ubuntu快捷更pip源

py安装: apt-get install python3-pip终端输入: pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/

图论基础知识 深度搜索(DFS,Depth First Search),广度搜索(BFS,Breathe First Search)

图论基础知识 学习记录自代码随想录 dfs 与 bfs 区别 dfs是沿着一个方向去搜&#xff0c;不到黄河不回头&#xff0c;直到搜不下去了&#xff0c;再换方向&#xff08;换方向的过程就涉及到了回溯&#xff09;。 bfs是先把本节点所连接的所有节点遍历一遍&#xff0c;走到下…

【React】Day6

项目搭建 基于CRA创建项目 CRA是一个底层基于webpack快速创建React项目的脚手架工具 # 使用npx创建项目 npx create-react-app react-jike# 进入到项 cd react-jike# 启动项目 npm start调整项目目录结构 -src-apis 项目接口函数-assets 项目资源文件&…

JavaEE初阶——多线程(六)——线程池

T04BF &#x1f44b;专栏: 算法|JAVA|MySQL|C语言 &#x1faf5; 小比特 大梦想 此篇文章与大家分享多线程的第六篇文章,关于线程池 如果有不足的或者错误的请您指出! 目录 3.线程池3.1标准库的线程池3.2 标准库自己提供的几个工厂类3.3自己实现一个线程池完成大体框架接下来完…

Hive架构原理

Hive Hive 的架构是设计用于在大数据环境下进行数据仓库操作和分析的系统。它建立在 Hadoop 生态系统之上&#xff0c;利用 Hadoop 的存储&#xff08;HDFS&#xff09;和计算&#xff08;MapReduce、Tez、Spark 等&#xff09;能力。 1. 元数据存储&#xff08;Metastore&am…

go语言并发实战——日志收集系统(六) 编写日志收集系统客户端

上节回顾 在上一篇文章中我们介绍了编写客户端的四个步骤&#xff0c;分别是&#xff1a; 读取配置文件&#xff0c;寻找日志路径初始化服务根据日志路径l来收集日志将收集到的日志发送Kafka中 关于上述的内容博主画了一个思维导图(有点丑&#xff0c;大家勉强看看&#xff0…

iOS - 多线程-GCD

文章目录 iOS - 多线程-GCD1. 常见多线程方案2. GCD2.1 GCD的常见函数GCD中有2个用来执行任务的函数 2.2 GCD的队列2.2.1 GCD的队列可以分为2大类型 2.3 容易混淆的术语2.4.1 有4个术语比较容易混淆&#xff1a;同步、异步、并发、串行 2.4 各种队列的执行效果 3. 死锁3.1 死锁…