【Socket】之TCP数据报套接字

news2024/12/25 9:12:17

1. 介绍下API

1.1 ServerSocket API

这是创建TCP服务端Socket的API。

构造方法方法说明
ServerSocket(int port)创建一个服务端流套接字Socket,并绑定到指定端口
普通方法方法说明
ServerSocket.accept()开始监听指定端口(创建时绑定的端口),有客户端连接后,返回一个服务端Socket对象,并基于该Socket建立与客户端的连接,否则阻塞等待
void close()关闭此套接字

1.2 Socket API

Socket 是客户端Socket,或服务端中接收到客户端建立连接(accept方法)的请求后,用来接收返回的服务端Socket。
不管是客户端还是服务端Socket,都是双方建立连接以后,保存的对端信息,及用来与对方收发数据
的。

构造方法方法说明
Socket(String host, int port)创建一个客户端套接字Socket,并于对应的ip的主机上,对应端口进程建立连接
普通方法方法说明
InputStream getInputStream()返回此套接字的输入流
OutputStream getOutputStream()返回此套接字的输出流

1.3 TCP中长短连接

TCP发送数据时,需要先建立连接,什么时候关闭连接就决定是短连接还是长连接:

短连接:每次接收到数据并返回响应后,都关闭连接,即是短连接。也就是说,短连接只能一次收发数据。

长连接:不关闭连接,一直保持连接状态,双方不停的收发数据,即是长连接。也就是说,长连接可以多次收发数据。

对于长短连接区别:

  • 建立连接、关闭连接耗时:短连接每次请求响应都需要建立连接,关闭连接;而长连接只需要建立第一次连接,之后的请求、响应可以直接传输。相对来说建立连接,关闭连接也是耗时的,长连接效率更高。
  • 主动发送请求不同:短连接一般是客户端主动向服务器端发送请求;而长连接可以是客户端主动发送请求,也可以是服务端主动发。
  • 两者场景不同,短连接适用于客户端请求频率不高的场景,如浏览网页;长连接适用于客户端与服务器通信频繁的场景,如聊天室,实时打游戏等。

2. 代码案例

2.1 服务器端(TcpEchoServer)

public class TcpEchoServer {
    private ServerSocket serverSocket = null;   // 外场销售

    public TcpEchoServer(int port) throws IOException {
        serverSocket = new ServerSocket(port);
    }

    public void start() throws IOException {
        ExecutorService executorService = Executors.newCachedThreadPool();
        System.out.println("服务器启动!");
        while (true) {
            Socket clientSocket = serverSocket.accept();   // 内场销售好多个
            // 如果直接调用,该方法会导致这个循环的二次执行,导致accept不及时
            // 创建新的线程,用新线程调用 processConnection
            // 每次来一个新的客户端都搞一个新的的线程即可!
//            Thread t = new Thread(()->{
//                try {
//                    processConnection(clientSocket);
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
//            });
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    try {
                        processConnection(clientSocket);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }

    // 通过这个方法来处理一个连接
    // 读取请求
    // 根据请求计算相应
    // 把响应返回给客户端
    private void processConnection(Socket clientSocket) throws IOException {
        System.out.printf("[%s:%d] 客户端上线!\n",clientSocket.getInetAddress().toString(),
                clientSocket.getPort());
        // try() 这种写法, ()中允许写多个流对象。 使用 ; 来分割
        try (InputStream inputStream = clientSocket.getInputStream();
             OutputStream outputStream = clientSocket.getOutputStream()) {
            Scanner scanner = new Scanner(inputStream); // 字符流
            PrintWriter printWriter = new PrintWriter(outputStream);
            while (true) {
                // 1,读取请求
                if (!scanner.hasNext()){
                    // 读取的流到结尾(对端关闭了)
                    System.out.printf("[%s:%d] 客户端下线!\n",clientSocket.getInetAddress().toString(),
                            clientSocket.getPort());
                    break;
                }
                // 直接使用 scanner 读取一段字符串
                String request = scanner.next();
                // 2. 根据请求计算相应
                String response = process(request);
                // 3. 把相应返回客户端
                printWriter.println(response);
                printWriter.flush();
                System.out.printf("[%s:%d] req: %s; resq: %s\n", clientSocket.getInetAddress().toString(),
                        clientSocket.getPort(),request,response);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            clientSocket.close();
        }
    }

    private String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        TcpEchoServer tcpEchoServer = new TcpEchoServer(9090);
        tcpEchoServer.start();
    }
}

2.2 客户端(TcpEchoClient)

public class TcpEchoClient {

    private Socket socket = null;

    public TcpEchoClient(String serverIp, int port) throws IOException {
        socket = new Socket(serverIp, port);
    }

    public void start() {
        Scanner scanner = new Scanner(System.in);
        try (InputStream inputStream = socket.getInputStream();
             OutputStream outputStream = socket.getOutputStream()) {
            PrintWriter printWriter = new PrintWriter(outputStream);
            Scanner scannerFromSocket = new Scanner(inputStream);
            while (true) {
                // 1.从键盘上读取用户输入的内容
                System.out.print("->");
                String request = scanner.next();
                // 2.把读取的内容构造成请求,发送给服务器
                // 注意这里发送 是带有换行
                printWriter.println(request);
                printWriter.flush();  // 此处需要手动刷新缓冲区
                // 3.从服务器读取相应内容
                String response = scannerFromSocket.next();
                // 4.把相应结果显示到控制台上
                System.out.printf("req: %s, resq: %s\n", request, response);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws IOException {
        TcpEchoClient tcpEchoClient = new TcpEchoClient("127.0.0.1",9090);
        tcpEchoClient.start();
    }
}

2.3 流程图

下面用一个流程图,来讲解代码是如何配合工作的
在这里插入图片描述

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

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

相关文章

Spring学习——Nginx

Nginx概述 Nginx介绍 Nginx是一款轻量级的web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器。其特点是占有内存少,并发能力强,事实上nginx的并发能力在同类型的网页服务器中表现较好,中国大陆使用nginx的网…

Python学习之DateTime

文章目录 前言一、pandas是什么?二、使用步骤1.引入库2.使用date.today()打印日期3.Python当前日期和时间:now() today()总结 4.如何使用 Strftime()格式化日期和时间输出1. 首先,我们将看到一个简单的如何格式化年份的步骤。通过一个例子来理…

【微服务笔记18】微服务组件之Gateway实现服务限流(计数器算法、漏桶算法、令牌桶算法)

这篇文章,主要介绍微服务组件之Gateway实现服务限流(计数器算法、漏桶算法、令牌桶算法)。 目录 一、服务限流 1.1、几种限流算法 (1)计数器算法 (2)漏桶算法 (3)令…

叮咚,你的耳鼻喉专科医院营销策略快来查收

进入后疫情时代以来,人们对健康意识的不断提高,医疗行业也开始卷起来了,通过各种渠道来宣传和推广医院,吸引更多的患者。那么今天就以耳鼻喉专科医院为主,聊聊这类医院该怎么在Z时代做好营销。 医院营销可以分为线上和…

【行为型模式】观察者模式

文章目录 1、概述2、结构3、实现方式3.1、案例引入3.2、结构分析3.3、具体实现 4、观察者模式优缺点5、应用场景 1、概述 观察者模式(Observer)是一种行为设计模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,其他所有依…

【C++】二叉搜索树的应用

前言 二叉搜索树本质也是二叉树,但因为其数据存储的特殊 — 左子树的值都更小,右子树的值都更大,所以在大部分情况下,查找更为高效。本篇博客将讲述二叉搜索树两个应用搜索的场景 那么话不多说,马上开始今天的学习。 文…

linux运维必了解的日志文件系统

目录 一、inode与block1.1inode和block概述1.1.1inode和block的关系 1.2inode的内容1.2.1inode包含文件的元信息1.2.2linux文件系统的三个时间戳1.2.3目录文件结构 1.3inode的号码1.3.1 硬盘分区后的结构 1.4inode的大小1.5恢复误删除的xfs文件1.6EXT类型文件恢复误删除 二、分…

亿发软件:玩具批发行业需要怎样的进销存开单软件

中国玩具市场的发展潜力十分巨大,近五年来中国玩具行业的批发零售企业都保持着良好的发展态势。近年来,在数字化转型的时代浪潮下,玩具批发零售市场想实现进一步的高质量发展,充分满足客户多元化的供货需求,需要向数据…

Qt5 和 OpenCV4 计算机视觉项目:6~9

原文:Qt 5 and OpenCV 4 Computer Vision Projects 协议:CC BY-NC-SA 4.0 译者:飞龙 本文来自【ApacheCN 计算机视觉 译文集】,采用译后编辑(MTPE)流程来尽可能提升效率。 当别人说你没有底线的时候&#x…

OpenCV 图像处理学习手册:6~7

原文:Learning Image Processing with OpenCV 协议:CC BY-NC-SA 4.0 译者:飞龙 本文来自【ApacheCN 计算机视觉 译文集】,采用译后编辑(MTPE)流程来尽可能提升效率。 当别人说你没有底线的时候,…

javascript之数组

创建 有以下几种方式 1.构造函数 在使用构造函数时,可以不带new 创建空数组 let color new Array() 或者let color Array() 创建指定个数元素的数组 let color new Array(2) 或者let color Array(2) 创建指定元素的数组 let color new Array("bl…

atio函数和宏offset的介绍

目录 前言atoi函数宏offsetof总结 前言 本章带大家一起认识一些在我们C语言标准库中的函数 atoi函数 int atio(const char* str);头文件&#xff1a; #include<stdlib.h>参数&#xff1a; str指向常量字符串起始位置的指针 函数介绍&#xff1a; ①解析C语言字符串str,…

2023软件测试工程师必备技能?要卷,谁还不会了......

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 软件测试岗位是怎…

FPGA基于Tri Mode Ethernet MAC实现UDP通信 提供3套工程源码和技术支持

目录 1、前言2、我这里已有的UDP方案3、米联客UDP协议栈4、详细设计方案5、Tri Mode Ethernet MAC的使用6、vivado工程1详解7、vivado工程2详解8、vivado工程3详解9、上板调试验证并演示10、福利&#xff1a;工程代码的获取 1、前言 目前网上的fpga实现udp基本生态如下&#x…

Spring Security实战(五)—— 密码加密

一、密码加密的演进 MD5 (Message-Digest Algorithm 5) 和 SHA (Secure Hash Algorithm) 是两种常见的消息摘要算法&#xff0c;它们都被用于加密和数据完整性验证等领域。 MD5 是一种 128 位的哈希函数&#xff0c;常用于数据完整性校验和数字签名等方面。它将任意长度的信息…

WebServer项目(四)->(基于Proactor的c++)Web服务器简介及简单实现

基于Proactor的cWeb服务器项目 WebServer项目(四)-&#xff1e;(基于Proactor的c)Web服务器简介及简单实现1.Web Server&#xff08;网页服务器&#xff09;2.HTTP协议(应用层的协议)3.HTTP 请求报文格式4.HTTP响应报文格式5.HTTP请求方法6.HTTP状态码7.服务器编程基本框架8.两…

分布式搜索技术elasticsearch概念篇

文章目录 一、分布式搜索技术二、elasticsearch2.1 初识elasticsearch2.2 正向索引和倒排索引2.2.1 介绍2.2.2 优缺点 2.3 elasticsearch和mysql的对比 一、分布式搜索技术 分布式搜索技术是一种基于分布式计算的搜索引擎技术&#xff0c;它使用多台计算机协同工作来处理大规模…

ElementUI登陆表单中常用的标签属性

ElementUI官网 为登陆框添加一个边角弧度 <style> .className{/*设置div边边框角的弧度*/border-radius: 10px; } </style><el–input>标签常用属性 <!--使用prefix属性添加一个前缀图标--> <el-input prefix-icon"el-icon-user-solid"&g…

深度学习第J6周:ResNeXt-50实战解析

目录 一、模型结构介绍 二、前期准备 三、模型 三、训练运行 3.1训练 3.2指定图片进行预测 &#x1f368; 本文为[&#x1f517;365天深度学习训练营]内部限免文章&#xff08;版权归 *K同学啊* 所有&#xff09; &#x1f356; 作者&#xff1a;[K同学啊] &#x1f4cc; …

大数据技术之集群数据迁移

在大数据集群数据迁移的项目中涉及到很多技术细节&#xff0c;本博客记录了迁移的大致的操作步骤。 迁移借用Hadoop自带的插件&#xff1a;distcp。 一、Hadoop集群数据迁移 **DistCp&#xff08;分布式拷贝&#xff09;**是用于大规模集群内部和集群之间拷贝的工具。它使用M…