【JavaEE】网络编程---TCP数据报套接字编程
一、TCP数据报套接字编程
1.1 ServerSocket API
ServerSocket
是创建TCP服务端Socket的API
ServerSocket
构造方法:
ServerSocket
方法:
1.2 Socket API
Socket
是客户端Socket
,或服务端中接收到客户端建立连接(accept
方法)的请求后,返回的服务端Socket
。不管是客户端还是服务端Socket
,都是双方建立连接以后,保存的对端信息,及用来与对方收发数据的。
Socket
构造方法:
Socket
方法:
通过上述字节流对象进行数据传输:
从InputStream
读数据就相当于从网卡接收
从OutputStream
写数据就相当于从网卡发送
1.3 短连接和长连接
短连接:一次连接只有一个请求
长连接:一次连接有多个请求
1.4 示例一:回显服务器(echo server)
这里我们演示长连接:
1.4.1 Tcp服务器
package 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;public class TcpEchoServer {//serverSocket是外场拉客的小哥,serverSocket有且只有一个//cilentSocket是内场服务的小姐姐,cilentSocket会给每个客户端分配一个private ServerSocket serverSocket = null;public TcpEchoServer(int port) throws IOException {serverSocket = new ServerSocket(port);}public void start() throws IOException {System.out.println("服务器启动!");while(true) {Socket cilentSocket = serverSocket.accept();processConnection(cilentSocket); //连接后通过processConnection来处理连接}}//通过这个方法来处理一个连接://1.读取请求//2.根据请求计算响应//3.把响应返回给客户端private void processConnection(Socket clientSocket) throws IOException {System.out.printf("[%s:%d] 客户端上线!\n", clientSocket.getInetAddress().toString(),clientSocket.getPort()); //提示客户端上线并打印IP地址和端口号//try()这种写法,允许括号中写多个流对象,中间使用“;”来分割try (InputStream inputStream = clientSocket.getInputStream();OutputStream outputStream = clientSocket.getOutputStream()) {Scanner scanner = new Scanner(inputStream); //为了读取请求方便,把字节流转为字符流PrintWriter printWriter = new PrintWriter(outputStream); //为了返回响应方便,把字节流转为字符流//我们读到哪里算是一个完整的请求呢;//此处做一个简单的约定://每个请求是个字符串(文本数据),每个请求之间使用\n来分割,不要忘记响应也要这样约定while(true) { //长连接:一次连接有多个请求//1.读取请求if (!scanner.hasNext()) { //如果客户端关闭连接了,hasNext返回false,结束while循环System.out.printf("[%s:%d] 客户端下线!\n",clientSocket.getInetAddress().toString(),clientSocket.getPort()); //提示客户端下线并打印IP地址和端口号break;}//如果没有读完,直接使用scanner读取一段字符串String request = scanner.next(); //next会往后一直读直到读到空白符(空格、换行符、制表符、翻页符等)结束(不包含空白符)。此处尽量不要使用nextLine//2.根据请求计算响应String response = process(request); //通过process方法来处理请求并返回响应//3.把响应返回给客户端(不要忘记响应里面也是要带上换行的,方便客户端区分从哪里到哪里是一个响应)printWriter.println(response);System.out.printf("[%s:%d] req:%s ; resp:%s \n",clientSocket.getInetAddress().toString(),clientSocket.getPort(),request,response);}} catch (IOException e) {e.printStackTrace();} finally {clientSocket.close(); //这里的cilentSocket只是给一个连接提供帮助,所以要及时释放}}private String process(String request) {return request;}public static void main(String[] args) throws IOException {TcpEchoServer tcpEchoServer = new TcpEchoServer(9090);tcpEchoServer.start();}
}
注意:如果没有客户端连接时,accept是会阻塞的
1.4.2 Tcp客户端
package 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;private void TcpEchoServer(String serverIP, int port) throws IOException {//这个操作就相当于让客户端和服务端建立Tcp连接了socket = new Socket(serverIP,port);}public void start() throws IOException {Scanner scanner = new Scanner(System.in);try (InputStream inputStreamt = socket.getInputStream(); OutputStream outputStream = socket.getOutputStream()){PrintWriter printWriter = new PrintWriter(outputStream);Scanner scanner1 = new Scanner(inputStreamt);while (true) {//1.从键盘上读取用户输入的内容System.out.println("->");String request = scanner.next();//2.把输入的内容构造成请求并发送给服务器(对应服务器的接收)//注意这里发送的请求带有换行printWriter.println(request);//3.从服务器读取相应内容String response = scanner1.next();//4.把响应结果显示在控制台上System.out.printf("req: %s; resp: %s\n", request, response);}}}public static void main(String[] args) throws IOException {TcpEchoClient client = new TcpEchoClient("127.0.0.1", 9090);client.start();}}
我们运行发现:
此时服务器已经启动且客户端也上线了,我们输入的请求为什么没有响应呢?
我们服务器这里的代码:
在这两个地方加上就可以正常运行了:
这样子我们的代码貌似没什么问题了
可是这里还有一个很严重的bug:咱们的服务器一次只能给一个客户端提供服务!!
在idea中默认只能启动一个客户端,我们需要稍微设置一下:
此时可以有两个客户端:
但是我们发现只有一个客户端上线了:
在第一个客户端输入正常,第二个没有任何响应:
当前服务器无法服务多个客户端!!!===》代码bug
怎么解决这个问题呢?
我们希望能够该客户端1提供循环服务的同时又能够循环的调用accept
我们对服务器代码的start
函数做如下改变:
public void start() throws IOException {System.out.println("服务器启动!");while(true) {Socket cilentSocket = serverSocket.accept();// 如果直接调用, 该方法会影响这个循环的二次执行, 导致 accept 不及时了.// 创建新的线程, 用新线程来调用 processConnection// 每次来一个新的客户端都搞一个新的线程即可Thread t = new Thread(() -> {try {processConnection(cilentSocket); //连接后通过processConnection来处理连接} catch (IOException e) {throw new RuntimeException(e);}});t.start();}}
此时服务器便可同时处理多个客户端:
相关文章:

【JavaEE】网络编程---TCP数据报套接字编程
一、TCP数据报套接字编程 1.1 ServerSocket API ServerSocket 是创建TCP服务端Socket的API ServerSocket 构造方法: ServerSocket 方法: 1.2 Socket API Socket 是客户端Socket,或服务端中接收到客户端建立连接(accept方法&…...

用 Go 访问 MySql 数据库
所有代码样例 package mainimport ("database/sql""fmt"_ "github.com/go-sql-driver/mysql" )var db *sql.DB// 初始化连接 func initDB() (err error) {db, err sql.Open("mysql", "root:mm..1213tcp(127.0.0.1:3306)/chapte…...

mac 升级node到指定版本
node版本14.15.1升级到最新稳定版18.18.2 mac系统 先查看一下自己的node版本 node -v开始升级 第一步 清除node的缓存 sudo npm cache clean -f第二步 安装n模块【管理模块 n是管理 nodejs版本】 sudo npm install -g n第三步升级node sudo n stable // 把当前系统的 Node…...

欢迎进QQ群讨论交流
...
C语言解决八皇后问题
八皇后问题是指在一个88的棋盘上,放置8个皇后,使得任意两个皇后都不能在同一行、同一列或同一斜线上。这是一个著名的递归问题。下面是一个C语言实现八皇后问题的代码,以及对代码的讲解。 #include <stdio.h>int board[8][8] {0}; //…...
springboot集成canal,将数据发送至接口
前置条件: mysql开启binlog日志部署canal服务 Springboot代码: 接口工具类: import cn.hutool.http.HttpRequest; import cn.hutool.http.HttpResponse; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; imp…...

Selenum八种常用定位(案例解析)
Selenium是一个备受推崇的工具。它有着丰富的功能,让我们能够与网页互动,执行各种任务,能为测试工程师和开发人员提供了很大的便利。 要充分利用Selenium,就需要了解如何正确定位网页上的元素。 接下来我将带大家共同探讨Seleni…...

Web前端接入Microsoft Azure AI文本翻译
Azure 文本翻译是 Azure AI 翻译服务的一项基于云的 REST API 功能。 文本翻译 API 支持实时快速准确地进行源到目标文本翻译。 文本翻译软件开发工具包 (SDK) 是一组库和工具,可用于轻松地将文本翻译 REST API 功能集成到应用程序中。 文本翻译 SDK 可跨 C#/.NET、…...

容联七陌助力鱼跃医疗升级智能联络中心,让客户服务更“鱼跃”
在当今高度竞争的市场环境中,企业的客户服务质量对于维护品牌形象和保持竞争优势至关重要。而随着人工智能、大数据等技术快速发展,智能化客户服务正在成为各行各业发展的重要部分。 鱼跃医疗是一家致力于“用科技律动生命"的国内知名医疗制造企业…...

【Redis系列】在Centos7上安装Redis5.0保姆级教程!
哈喽, 大家好,我是小浪。那么最近也是在忙秋招,很长一段时间没有更新文章啦,最近呢也是秋招闲下来,当然秋招结果也不是很理想,嗯……这里就不多说啦,回归正题,从今天开始我们就开始正…...

线性代数-Python-03:矩阵的变换 - 手写Matrix Transformation及numpy中的用法
文章目录 一、代码仓库二、旋转矩阵的推导及图形学中的矩阵变换2.1 让横坐标扩大a倍,纵坐标扩大b倍2.2 关于x轴翻转2.3 关于y轴翻转2.4 关于原点翻转(x轴,y轴均翻转)2.5 沿x方向错切2.6 沿y方向错切2.7 旋转2.8 单位矩阵2.9 矩阵的…...

【单片机基础】按键状态机实现短按、长按、双击、三击和N击
下载地址: 【CSDNNaiva】源码:HK32F030M-按键扫描-短按长按检测【CSDNNaiva】源码:HK32F030M-ADC-EXTI-TM1624-USART-EEPROM-TiMBase-按键长按(231024) 参考资料 [1] 【CSDNPillarPeng】【按键】[独立按键] - 1: 单击,…...

Ubuntu虚拟机部署OpenStack
1、部署环境 系统:ubuntu-22.04.3-desktop-amd64DevStack版本:2024.1VMware Workstation:8G内存、4核处理器、100G硬盘/1、网络NAT模式/1 2、Ubuntu环境设置 点击show applications,选择Software&Updates 跟换Ubuntu的镜像…...

ES在企业项目中的实战总结,彻底掌握ES的使用
通过之前两篇文章 了解了ES的核心概念和基础使用学习进阶的DSL语法处理复杂的查询 这段时间通过在本企业代码中对ES框架的使用,总结了不少经验。主要分为三点 企业封装了ES原生的api,需要使用企业项目提供的接口实现 -------简单使用(本章节目…...

QT的Qporcess功能的使用
具体实现代码如下: #include <QProgressBar>//必须要包含的头文件 #include <QProcess>// 创建一个QProgressBar对象QProgressBar *progressBar new QProgressBar(this);QProcess *proces;process_shownew process;// 设置进度条的最小值和最大值prog…...

【图灵诸葛】jvm笔记
2023年10月23日14:04:44 jvm 1.jdk体系结构图回顾(Av333129672,P1) jdk jre 底层是hotspot jvm 2.java虚拟机内部组成(Av333129672,P2) 堆 方法区 执行引擎 类加载 本地方法栈 线程栈(虚拟机栈) 3.java虚拟机栈讲解(Av333129672,P3) 程序计数器…...

数据安全小课堂开讲啦!看这里!
数据安全小课堂开讲啦!看这里! 1、什么是数据? 《数据安全法》第三条明确,本法所称的数据,就是指任何以电子或者其他方式对信息的记录。小到个人使用手机、电脑等电子产品时浏览的网页、下载的应用、存储的文件&…...

单片机矩阵键盘
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、什么是矩阵键盘?1.独立键盘2.矩阵键盘变化1变化2变化3 3. 通过变型,举一反三,就可以实现4*4的矩阵键盘扫描 二、使用步骤…...

横坐标日期等间隔绘图 python示例代码
有两列数据,一列是日期,另一列是数值。日期是递增的,但是间隔不是均匀的。比如1月1日至2月1日有10组数据,2月1日至3月1日有100组数据,3月1日至4月1日有1000组数据。我想绘折线图,横坐标是日期,纵…...

photoshop2024免费插件Portraiture3
随着手机摄影的普及,修图可以说是现代人的必备生活技能之一了,现在谁发个朋友圈不把自己的照片修的美美的呢?那么如何拥有一张氛围感满满的照片呢?这不得不提图片处理软件中的王牌——photoshop。作为专业的图片处理软件ÿ…...

测试微信模版消息推送
进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...

TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...

3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...

DAY 47
三、通道注意力 3.1 通道注意力的定义 # 新增:通道注意力模块(SE模块) class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...
Leetcode 3577. Count the Number of Computer Unlocking Permutations
Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接:3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯,要想要能够将所有的电脑解锁&#x…...

Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...

Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...

人机融合智能 | “人智交互”跨学科新领域
本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...