当前位置: 首页 > news >正文

TCP Socket API 讲解,以及回显服务器客户端的实现

文章目录

    • TCP
      • ServerSocket API
      • Socket API
    • TCP 客户端服务器的实现

TCP

ServerSocket API

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

serverSocket构造方法:

方法签名方法说明
ServerSocket(int port)创建一个服务端流套接字Socket,并绑定到指定端口

serverSocket方法:

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

Socket API

Socket 是客户端Socket,或服务端中接收到客户端建立连接(accept方法)的请求后,返回的服务端 Socket。

不管是客户端还是服务端Socket,都是双方建立连接以后,保存的对端信息,及用来与对方收发数据的。

Socket 构造方法:

方法签名方法说明
Socket (String host, int port)创建一个客户端流套接字Socket,并与对应IP的主机上,对应端口的进程建立连接

Socket 方法:

方法签名方法说明
InetAddress getInetAddress()返回套接字所连接的地址
InputStream getInputStream()返回此套接字的输入流
OutputStream getOutputStream()返回此套接字的输出流

TCP 客户端服务器的实现

因为 TCP 是面向连接的,所以TCP 服务器是需要多线程的,每个客户端连接都需要一个独立的线程来处理数据的收发和状态的维护,否则一个客户端的阻塞会影响其他客户端的正常通信。因此,TCP 服务器需要多线程来支持多个客户端的连接和通信

核心思路

  1. 服务器:

    • 首先给给这个服务器绑定一个端口号。(port:9090)

    • 启动服务器,利用 accept 方法建立与客户端的连接。

    • 建立线程池,后续操作在线程池中执行。

    • 接收客户端发送过来的请求。

    • 根据请求计算响应并发回,注意要添加一条“刷新缓冲区 (flush)”的操作。(回显服务器,响应值就是请求值)

    • 最后打印日志。

  2. 客户端:

    • 完成连接 TCP 服务器的操作。(ip: 127.0.0.1 , port: 9090)
    • 启动客户端,从控制台输入请求。
    • 把请求发送给服务器,同时还要加上刷新缓冲区 (flush) 的操作。
    • 最后读取服务器响应,并打印响应结果。
  3. 注意:

    因为 TCP 是字节流,所以利用 InputStream【Scanner】 和 OutputStream【PrintWriter】来读取或发送数据,由于InputStream 和 OutputStream 生命周期短,因此要及时 close(),这里我们用到 try-with-resources。

Java 打印流 PrintWriter 的介绍:PrintWriter 是 Java 中的一个字符类型的打印输出流,PrintWriter 可以将数据写入文件或其他输出流中,下面代码中用于 服务器向客户端发送数据/客户端向服务器发送数据

TCP 服务器的实现:

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class TcpEchoServer {private ServerSocket serverSocket = null;// 此处不应该创建固定线程数目的线程池.private ExecutorService service = Executors.newCachedThreadPool();// 这个操作就会绑定端口号public TcpEchoServer(int port) throws IOException {serverSocket = new ServerSocket(port);}// 启动服务器public void start() throws IOException {System.out.println("服务器启动!");while (true) {// 这个写法, 是能自动关闭, 也行. 实现 Closeable 接口就可以这么写.// 这么写会有其他问题. (结合后面讲第二个问题, 再说这个事)Socket clientSocket = serverSocket.accept();// 使用线程池, 来解决上述问题service.submit(new Runnable() {@Overridepublic void run() {processConnection(clientSocket);}});}}// 通过这个方法来处理一个连接的逻辑.private void processConnection(Socket clientSocket) {System.out.printf("[%s:%d] 客户端上线!\n", clientSocket.getInetAddress().toString(), clientSocket.getPort());// 接下来就可以读取请求, 根据请求计算响应, 返回响应三步走了.// Socket 对象内部包含了两个字节流对象, 可以把这俩字节流对象获取到, 完成后续的读写工作try (InputStream inputStream = clientSocket.getInputStream();OutputStream outputStream = clientSocket.getOutputStream()) {// 一次连接中, 可能会涉及到多次请求/响应while (true) {// 1. 读取请求并解析. 为了读取方便, 直接使用 Scanner.Scanner scanner = new Scanner(inputStream);if (!scanner.hasNext()) {// 读取完毕, 客户端下线.System.out.printf("[%s:%d] 客户端下线!\n", clientSocket.getInetAddress().toString(), clientSocket.getPort());break;}// 这个代码暗含一个约定, 客户端发过来的请求, 得是文本数据, 同时, 还得带有空白符作为分割. (比如换行这种)String request = scanner.next();// 2. 根据请求计算响应String response = process(request);// 3. 把响应写回给客户端. 把 OutputStream 使用 PrinterWriter 包裹一下, 方便进行发数据.PrintWriter writer = new PrintWriter(outputStream);//    使用 PrintWriter 的 println 方法, 把响应返回给客户端.//    此处用 println, 而不是 print 就是为了在结尾加上 \n . 方便客户端读取响应, 使用 scanner.next 读取.writer.println(response);//    这里还需要加一个 "刷新缓冲区" 操作.writer.flush();// 日志, 打印当前的请求详情.System.out.printf("[%s:%d] req: %s, resp: %s\n", clientSocket.getInetAddress().toString(), clientSocket.getPort(), request, response);}} catch (IOException e) {e.printStackTrace();} finally {// 在 finally 中加上 close 操作, 确保当前 socket 被及时关闭!!try {clientSocket.close();} catch (IOException e) {e.printStackTrace();}}}public String process(String request) {return request;}public static void main(String[] args) throws IOException {TcpEchoServer server = new TcpEchoServer(9090);server.start();}
}

TCP 客户端代码:

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;public class TcpEchoClient {private Socket socket = null;// 要和服务器通信, 就需要先知道, 服务器所在的位置.public TcpEchoClient(String serverIp, int serverPort) throws IOException {// 这个 new 操作完成之后, 就完成了 tcp 连接的建立.socket = new Socket(serverIp, serverPort);}public void start() {System.out.println("客户端启动");Scanner scannerConsole = new Scanner(System.in);try (InputStream inputStream = socket.getInputStream();OutputStream outputStream = socket.getOutputStream()) {while (true) {// 1. 从控制台输入字符串.System.out.print("-> ");String request = scannerConsole.next();// 2. 把请求发送给服务器PrintWriter printWriter = new PrintWriter(outputStream);//    使用 println 带上换行. 后续服务器读取请求, 就可以使用 scanner.next 来获取了printWriter.println(request);//    不要忘记 flush, 确保数据是真的发送出去了!!printWriter.flush();// 3. 从服务器读取响应.Scanner scannerNetwork = new Scanner(inputStream);String response = scannerNetwork.next();// 4. 把响应打印出来System.out.println(response);}} catch (IOException e) {e.printStackTrace();}}public static void main(String[] args) throws IOException {TcpEchoClient client = new TcpEchoClient("127.0.0.1", 9090);client.start();}
}

相关文章:

TCP Socket API 讲解,以及回显服务器客户端的实现

文章目录 TCPServerSocket APISocket API TCP 客户端服务器的实现 TCP ServerSocket API ServerSocket 是创建TCP服务端 Socket 的 API。 serverSocket构造方法: 方法签名方法说明ServerSocket(int port)创建一个服务端流套接字Socket,并绑定到指定端…...

2023年掌控安全学院CTF暖冬杯——数据流分析

前言:打工仔一枚,第一波上新的3题misc 做完了 再打ISCTF随便记录一下 PS:环境关了,题目描述忘记了,反正就是找flag。 筛选HTTP数据流 导出数据流慢慢看 ctrl F 搜flag 看到一条 有flag.txt 的数据 导出另存.zip 这里…...

UE4 基础篇十四:自定义插件

文末有视频地址和git地址 一、概念 虚幻里插件都是用C++写的,C++包括.h文件和.cpp文件,.h头文件通常包含函数类型和函数声明,cpp文件包含这些类型和函数的实现, 你为项目编写的所有代码文件都必须位于模块中,模块就是硬盘里的一个文件夹,包含名为“Build.cs”的C#文件…...

QT QGraphicsItem 图元覆盖导致鼠标点击事件不能传递到被覆盖图元

一、概述 在日常开发中,遇到这样一个问题,线图元和引脚图元重叠,导致点击引脚图元,没有进入引脚图元的鼠标点击事件中。 二、产生原因 如果您的 QGraphicsItem 上有一个图元覆盖了它,可能会导致鼠标事件无法正常触发…...

proto语法学习笔记

proto语法学习笔记 Protocol Buffers(Proto是由谷歌开发的一种数据序列化格式。 Proto 不是一种编程语言,而是一种接口描述语言(IDL),用于定义数据结构和消息格式。 它的设计目标是提供一种简单、高效、可扩展的方法来…...

python-nmap库使用教程(Nmap网络扫描器的Python接口)(功能:主机发现、端口扫描、操作系统识别等)

文章目录 Python-nmap库使用教程前置条件引入python-nmap创建Nmap扫描实例执行简单的主机发现(nmap -sn)示例,我有一台主机配置为不响应 ICMP 请求,但使用nmap -sn,仍然能够探测到设备: 端口扫描扫描特定端…...

什么是智慧工地?

一、什么是智慧工地? 工地本身不拥有智慧,工地的运作是依赖于人的智慧。工地信息化技术,能够减少对人的依赖,使工地拥有智慧。 智慧工地,就是立足于“智慧城市”和“互联网”,采用云计算、大数据和物联网等…...

【古月居《ros入门21讲》学习笔记】08_发布者Publisher的编程实现

目录 说明: 1. 话题模型 图示 说明 2. 实现过程(C) 创建功能包 创建发布者代码(C) 配置发布者代码编译规则 编译并运行 编译 运行 3. 实现过程(Python) 创建发布者代码(…...

沿着马可·波罗的足迹,看数字云南

刚入行的时候,有位前辈跟我说过一句话:去现场“要像外国人一样去看”,重新审视那些自己可能早已“熟视无睹”的事物。 前不久,我跟随“看见数字云南——云南数字经济媒体探营活动”,奔赴昆明、大理、西双版纳等地&…...

记录问题-使用@Validated报错Validation failed for argument [0]

类字段 NotNull(message "双坐标不能为空", groups {Insert.class, Update.class})private Integer yAxisType;接口 /*** 添加** return*/RequestMapping(value "/add", method RequestMethod.POST)public Result add(Validated(Insert.class) Request…...

three.js--立方体

作者:baekpcyyy🐟 使用three.js渲染出可以调节大小的立方体 1.搭建开发环境 1.首先新建文件夹用vsc打开项目终端 2.执行npm init -y 创建配置文件夹 3.执行npm i three0.152 安装three.js依赖 4.执行npm I vite -D 安装 Vite 作为开发依赖 5.根…...

App的测试,和传统软件测试有哪些区别?应该增加哪些方面的测试用例?

从上图可知,测试人员所测项目占比中,App测试占比是最高的。 这就意味着学习期间,我们要花最多的精力去学App的各类测试。也意味着我们找工作前,就得知道,App的测试点是什么,App功能我们得会测试&#xff0…...

改进LiteOS中物理内存分配算法(详细实验步骤+相关源码解读)

一、实验要求 优化TLSF算法,将Best-fit策略优化为Good-fit策略,进一步降低时间复杂度至O(1)。 优化思路: 1.初始化时预先为每个索引中的内存块挂上若干空闲块,在实际分配时避免分割(split)操作&#xff…...

洛谷100题DAY8

36.P1416 攻击火星 此题找出规律即可 #include<bits/stdc.h> using namespace std; int n; int main() {cin >> n;cout << max(0, n - 2);return 0; } 37.P1551 亲戚 并查集模板题目 两个人如果使亲戚就合并建立联系&#xff0c;最后进行查找即可 #incl…...

2. OpenHarmony源码下载

OpenHarmony源码下载(windows, ubuntu) 现在的 OpenHarmony 4.0 源码已经有了&#xff0c;在 https://gitee.com/openharmony 地址中&#xff0c;描述了源码获取的方式。下来先写下 windows 的获取方式&#xff0c;再写 ubuntu 的获取方式。 获取源码前&#xff0c;还需要的准…...

flask app.config 用法

flask app.config flask app.config 是 Flask 应用程序的配置对象。它包含了 Flask 应用程序的所有配置信息&#xff0c;如数据库连接、密钥、调试模式等。 常用的 app.config 配置项如下&#xff1a; DEBUG&#xff1a;调试模式&#xff0c;默认为 False。 SECRET_KEY&…...

【Vue】【uni-app】实现工单列表项详情页面

这次主要实现的是一个工单详情页面 从工单列表项中点击详情 跳转到工单详情页面&#xff0c;这个详情页面就是这次我们要实现的页面&#xff0c;并可以通过点击这个关闭按钮返回到工单列表页面 首先是在我们原有的工单列表页面的按钮增加一个点击跳转 <button size"m…...

安装vmware_esxi 超详细

安装vmware_esxi 超详细 </h2><div id"cnblogs_post_body" class"blogpost-body blogpost-body-html">esxi安装手册 1、esxi介绍 ESXI原生架构模式的虚拟化技术&#xff0c;是不需要宿主操作系统的&#xff0c;它自己本身就是操作系统。因此…...

Spring-Mybatis源码解析--手写代码实现Spring整合Mybatis

文章目录 前言一、引入&#xff1a;二、准备工作&#xff1a;2.1 引入依赖2.2 数据源的文件&#xff1a;2.1 数据源&#xff1a; 2.3 业务文件&#xff1a; 三、整合的实现&#xff1a;3.1 xxxMapper 接口的扫描&#xff1a;3.2 xxxMapper 接口代理对象的生成&#xff1a;3.2 S…...

5.2 Windows驱动开发:内核取KERNEL模块基址

模块是程序加载时被动态装载的&#xff0c;模块在装载后其存在于内存中同样存在一个内存基址&#xff0c;当我们需要操作这个模块时&#xff0c;通常第一步就是要得到该模块的内存基址&#xff0c;模块分为用户模块和内核模块&#xff0c;这里的用户模块指的是应用层进程运行后…...

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站&#xff0c;会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后&#xff0c;网站没有变化的情况。 不熟悉siteground主机的新手&#xff0c;遇到这个问题&#xff0c;就很抓狂&#xff0c;明明是哪都没操作错误&#x…...

简易版抽奖活动的设计技术方案

1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能

下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能&#xff0c;包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

家政维修平台实战20:权限设计

目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系&#xff0c;主要是分成几个表&#xff0c;用户表我们是记录用户的基础信息&#xff0c;包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题&#xff0c;不同的角色&#xf…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面

代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口&#xff08;适配服务端返回 Token&#xff09; export const login async (code, avatar) > {const res await http…...

Caliper 配置文件解析:config.yaml

Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

算法笔记2

1.字符串拼接最好用StringBuilder&#xff0c;不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...

安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖

在Vuzix M400 AR智能眼镜的助力下&#xff0c;卢森堡罗伯特舒曼医院&#xff08;the Robert Schuman Hospitals, HRS&#xff09;凭借在无菌制剂生产流程中引入增强现实技术&#xff08;AR&#xff09;创新项目&#xff0c;荣获了2024年6月7日由卢森堡医院药剂师协会&#xff0…...

现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?

现有的 Redis 分布式锁库&#xff08;如 Redisson&#xff09;相比于开发者自己基于 Redis 命令&#xff08;如 SETNX, EXPIRE, DEL&#xff09;手动实现分布式锁&#xff0c;提供了巨大的便利性和健壮性。主要体现在以下几个方面&#xff1a; 原子性保证 (Atomicity)&#xff…...

【JavaSE】多线程基础学习笔记

多线程基础 -线程相关概念 程序&#xff08;Program&#xff09; 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序&#xff0c;比如我们使用QQ&#xff0c;就启动了一个进程&#xff0c;操作系统就会为该进程分配内存…...