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

网络编程套接字之TCP

在这里插入图片描述

文章目录

  • 一、TCP流套接字编程
    • ServerSocket
    • Socket
    • TCP长短连接
  • 二、TCP回显服务器客户端
    • 服务器
    • 客户端
    • 并发服务器
    • UDP与TCP

一、TCP流套接字编程

我们来一起学习一下TCP socket api的使用,这个api与我们之前学习的IO流操作紧密相关,如果对IO流还不太熟悉的,可以看看这篇IO流操作

ServerSocket

顾名思义,ServerSocket是创建TCP服务器的Socket对象

构造方法作用
ServerSocket(int port)创建一个服务器套接字Socket,并指定端口号
方法作用
Socket accept()开始监听指定端口,有客户端连接时,返回一个服务端Socket对象,并基于该Socket对象与客户端建立连接,否则阻塞等待
void close()关闭此套接字

Socket

我们这里的Socket既是客户端的Socket,也可能是服务器接收到客户端连接后,返回的服务器Socket,不论是那个Socket,都是双方建立连接后,保存对方信息,进行收发数据的。

构造方法作用
Socket(String host,int port)创建一个客户端Socket对象,并与对应IP主机,对应端口的进程进行连接
方法作用
InetAddress getInetAddress()返回套接字所连接的地址
InputStream getInputStream()返回套接字的输入流
OutputStream getOutputStream()返回套接字的输出流

TCP长短连接

顾名思义,我们的TCP的长短连接,就表示我们TCP建立连接后,什么时候关闭连接就决定了是长连接还是短链接。
短连接: 在每次接收到数据并返回响应后,关闭连接。也就是说短连接只能收发一次数据。
长连接: 一直保持连接的状态,不关闭连接,双方可以不停的收发数据。

两者各有优缺,短连接适用于客户端请求频率不高的场景,浏览网页等。长连接适用于客户端与服务器频繁通信的场景,视频通话等。

二、TCP回显服务器客户端

服务器

有了昨天UDP实现的基础,今天我们的TCP实现已经有些部分就比较容易理解了。

public class EchoServer {private ServerSocket serverSocket = null;public EchoServer(int port) throws IOException {serverSocket = new ServerSocket(port);}
}

先创建TCP服务器Socket对象,并指定端口号。

Socket clientSocket = serverSocket.accept();

与客户端进行连接,如果没有获取到连接,则会发生阻塞等待,每获取到一个客户端连接就会返回一个Socket对象,该Socket对象是专门负责与连接的客户端进行通信的。
我们获取到的每一个Socket对象,可能会进行多次通信,所以我们获取到连接后,将通信封装成一个方法。

private void processCoonection(Socket clientSocket) {System.out.printf("[%s:%d] 客户端上线\n",clientSocket.getInetAddress().toString(),clientSocket.getPort());try(InputStream inputStream = clientSocket.getInputStream();OutputStream outputStream = clientSocket.getOutputStream()) {}catch (IOException e) {e.printStackTrace();}finally {try{clientSocket.close();}catch (IOException e) {e.printStackTrace();}}}

我们先获取与输出输入流,因为需要释放我们直接将它们放到try()中,然后在finally里释放Socket对象资源。

Scanner scanner = new Scanner(inputStream);if(!scanner.hasNext()) {//数据已经读完了System.out.printf("[%s:%d] 客户端下线\n",clientSocket.getInetAddress().toString(),clientSocket.getPort());break;}String request = scanner.next();

我们将输入流封装到Scanner里,从控制台输入,然后判断控制台是否还有数据输入,如果没有数据输入就退出,然后获取客户端的请求。

/直接返回客户端的请求String response = process(request);//将输出流封装成打印流PrintWriter printWriter = new PrintWriter(outputStream);printWriter.println(response);printWriter.flush();System.out.printf("[%s:%d] req: %s;resp: %s\n",clientSocket.getInetAddress().toString(), clientSocket.getPort(),request, response);

在这里插入图片描述

public class EchoServer {private ServerSocket serverSocket = null;public EchoServer(int port) throws IOException {serverSocket = new ServerSocket(port);}public void start() throws IOException {System.out.println("服务器启动!");while (true) {Socket clientSocket = serverSocket.accept();processCoonection(clientSocket);}}private void processCoonection(Socket clientSocket) {System.out.printf("[%s:%d] 客户端上线\n",clientSocket.getInetAddress().toString(),clientSocket.getPort());try(InputStream inputStream = clientSocket.getInputStream();OutputStream outputStream = clientSocket.getOutputStream()) {while (true) {Scanner scanner = new Scanner(inputStream);if(!scanner.hasNext()) {//数据已经读完了System.out.printf("[%s:%d] 客户端下线\n",clientSocket.getInetAddress().toString(),clientSocket.getPort());break;}String request = scanner.next();//直接返回客户端的请求String response = process(request);//将输出流封装成打印流PrintWriter printWriter = new PrintWriter(outputStream);printWriter.println(response);printWriter.flush();System.out.printf("[%s:%d] req: %s;resp: %s\n",clientSocket.getInetAddress().toString(), clientSocket.getPort(),request, response);}}catch (IOException e) {e.printStackTrace();}finally {try{clientSocket.close();}catch (IOException e) {e.printStackTrace();}}}public String process(String request) {return request;}
}

我们现在实现的这个TCP server有个致命的缺点,一次只能处理一个客户端,等我们写完客户端再来分析。

客户端

public class EchoClient {private Socket socket = null;public EchoClient(String serverIp,int serverPort) throws IOException {//我们TCP的Socket对象能够识别点分十进制的IP//我们在创建对象的时候,就会与服务器进行连接socket = new Socket(serverIp,serverPort);}
}

我们在new 这个对象的过程,就会触发TCP建立连接的过程,如果我们客户端没有这部分代码,那么服务器就会在accept进行阻塞等待。

public void start() {System.out.println("客户端启动!");Scanner scanner = new Scanner(System.in);try(InputStream inputStream = socket.getInputStream();OutputStream outputStream = socket.getOutputStream()) {while (true) {System.out.print("> ");String request = scanner.next();if(request.equals("exit")) {System.out.println("客户端退出!");break;}PrintWriter printWriter = new PrintWriter(outputStream);printWriter.flush();Scanner respScanner = new Scanner(inputStream);String response = respScanner.next();System.out.println(response);}}catch (IOException e) {e.printStackTrace();}}

我们客户端的收发数据与服务器大差不差,这里就不在一一解释了。
在这里插入图片描述
在这里插入图片描述
分别启动客户端服务器程序。

在这里插入图片描述
在这里插入图片描述
可以成功的收发数据,但是我们当前代码有一个很严重的问题,服务器同一时刻只能处理一个连接,这样是很鸡肋的,我们对服务器进行更新。

并发服务器

我们看观察一下我们服务器的代码。
在这里插入图片描述
当我们客户端连接上这个服务器的时候,就执行到processConnection方法的while循环中,只要该方法不结束,我们的accpet就无法获取到第二个客户端socket对象。
那么我们如何解决这个问题呢?
使用多线程,我们的主线程专门负责进行accept,每收到一个连接,创建新线程,由新线程来负责处理这个新的客户端。

public void start() throws IOException {System.out.println("服务器启动!");while (true) {Socket clientSocket = serverSocket.accept();Thread t = new Thread(() -> {processCoonection(clientSocket);});t.start();}}

我们可以使用多线程来解决这个问题,但是现在每获取到一个连接就会创建一个线程,如果同一时刻连接过多,我们创建了大量线程,资源全部耗费在了线程切换上面了,我们可以使用线程池来提升效率。

public void start() throws IOException {System.out.println("服务器启动!");ExecutorService threadPool = Executors.newCachedThreadPool();while (true) {Socket clientSocket = serverSocket.accept();threadPool.submit(() -> {processCoonection(clientSocket);});}}

尽管我们使用了线程池了,但还是不够,如果我们的客户端非常多,而且都迟迟不断开,就会导致我们会有很多线程,对于我们来说是一个很大的负担。
能否有办法解决单机支持更大量客户端的问题呢?也是经典的C10M(单机处理1KW个客户端)问题
这里并不是说单机真正能处理1KW个客户端,只是表达说客户端的量非常大,针对我们上述多线程的版本,我们的机器是承受不了这么多线程的开销的,那么是否有办法一个线程处理很多客户端连接呢? 这就是IO多路复用,IO多路转接技术
给线程安排一个集合,这个集合放了一堆连接,我们线程负责监听集合,那个连接有数据来了,就处理那个连接。虽然我们的连接有很多,但是我们这里的连接并不是严格意义上的同时,也是有先后的,我们的操作系统里,提供了一些API,比如select,poll,epoll,我们的java里,也提供了一组NIO这样的类,封装了上述技术。

UDP与TCP

我们学习了TCP与UDP的网络编程后,来进行一个对比。
TCP:
在这里插入图片描述
UDP:
在这里插入图片描述

相关文章:

网络编程套接字之TCP

文章目录一、TCP流套接字编程ServerSocketSocketTCP长短连接二、TCP回显服务器客户端服务器客户端并发服务器UDP与TCP一、TCP流套接字编程 我们来一起学习一下TCP socket api的使用,这个api与我们之前学习的IO流操作紧密相关,如果对IO流还不太熟悉的&am…...

网络与串口调试工具TCPCOM

TCPCOM,网络与串口二合一调试助手,将网络调试助手与串口调试助手合二为一,绿色软件,简单高效。【软件特色】 1. 支持中英文双语言,自动根据操作系统环境选择系统语言类型; 2. 支持ASCII/Hex发送,发送和接收…...

数据库常用命令

文章目录1. 数据库操作命令1.进入数据库2.查看数据库列表信息3.查看数据库中的数据表信息2.SQL语句命令1. 创建数据表2. 基本查询语句3. SQL排序4. SQL分组统计5. 分页查询6. 多表查询7.自关联查询8.子查询1. 数据库操作命令 1.进入数据库 mysql -uroot -p2.查看数据库列表信…...

PTA复习

函数 6-1 学生类的构造与析构 #include<bits/stdc.h> using namespace std; class Student {int num;string name;char sex; public:Student(int n,string nam,char s):num(n),name(nam),sex(s){cout<<"Constructor called."<<endl;}void display…...

TypeScript 学习之接口

接口&#xff1a;对值所具有的结构进行类型检查&#xff0c;称为“鸭式变型法”或“结构性子类型化” 基本使用 interface LabelledValue {label: string; }function printLabel(labelledObj: LabelledValue) {console.log(labelledObj.label); }let myObj {size: 10, label:…...

原码反码补码

在计算机中&#xff0c;负数都是以补码的形式存放的&#xff0c; 正数的原码、反码、补码完全一致。 原码&#xff1a;指的是正数的二进制或负数的二进制&#xff0c; 负数的二进制&#xff08;原码&#xff09;&#xff0c;其实就是在正数的二进制的最高位前面加一个符号位 1。…...

大数据选股智能推荐系统V1.0-1

很长时间没有发布博客了&#xff0c;这段时间个人确实有点忙。另外一方面在这段时间我也没有闲着。自己研发了一套大数据选股的智能推荐系统。废话不说&#xff0c;我们先来看这套系统&#xff1a;登录页面&#xff1a;&#xff08;技术点&#xff1a;验证码的生成&#xff09;…...

调研生成GIF表情包之路

调研阶段 gifshot.js合成GIF 可以从媒体流、视频或图像创建动画 GIF 的 JavaScript 库。 csdn地址&#xff1a;https://blog.csdn.net/qq_16494241/article/details/125717405 分解GIF图片、合成GIF图片 两步走&#xff1a; 1、分解GIF图片 libgif-js&#xff1a;JavaScrip…...

【RocketMQ】源码详解:生产者启动与消息发送流程

消息发送 生产者启动 入口 : org.apache.rocketmq.client.impl.producer.DefaultMQProducerImpl#start(boolean) 生产者在调用send()方法发送消息之前,需要调用start进行启动, 生产者启动过程中会启动一些服务和线程 启动过程中会启动MQClientInstance, 这个实例是针对一个项…...

信息安全(一)

思维导图 一、AES加解密 1.概述 1.1 概念 AES&#xff1a; 高级加密标准&#xff08;Advanced Encryption Standard&#xff09;是一种对称加密的区块加密标准。 &#xff08;1&#xff09;替代DES的新一代分组加密算法 &#xff08;2&#xff09;支持三种长度密钥&#x…...

企业多会场视频直播(主会场、分会场直播)实例效果

阿酷TONY 2023-2-16 长沙 活动直播做多会场切换功能&#xff08;主会场、分会场、会场一、会场二、会场三自由切换&#xff09; 企业多会场视频直播&#xff08;主会场、分会场直播&#xff09;实例效果 特点&#xff1a;支持PC端&#xff0c;也支持移动端观看&#xff0c;会…...

线性代数速览(一)行列式

文章目录行列式&#x1f33b; 行列式的定义&#x1f33c; 行列式的性质&#x1f337; 一些定理&#x1f940; 行列式的计算&#x1f33a; 克莱姆法则行列式 行列式的本质&#xff0c;就是一个数值。 &#x1f33b; 行列式的定义 有三种定义&#xff1a;1、按行展开&#xff…...

恭喜山东翰林“智慧园区管理系统”获易知微可视化设计大赛二等奖

数字化经济发展是全球经济发展的重中之重&#xff0c;“数字孪生&#xff08;Digital Twin&#xff09;”这一词汇正在成为学术界和产业界的一个热点。数字孪生作为近年来的新兴技术&#xff0c;其与国民经济各产业融合不断深化&#xff0c;推动着各大产业数字化、网络化、智能…...

gulp简单使用

gulp gulp的核心理念是task runner 可以定义自己的一系列任务 等待任务被执行 基于文件stream的构建流 我们可以使用gulp的插件体系来完成某些任务 webpack的核心理念是module bundler webpack是一个模块化的打包工具 可以使用各种各样的loader来加载不同的模块 可以使用各种…...

ce认证机构如何选择?

CE认证想必大家都已经有所了解&#xff0c;它是产品进入欧盟销售的通行证&#xff0c;那么我们在办理CE认证时该怎么进行选择?带大家了解一下CE认证机构&#xff0c;以及该怎么去进行选择? 以下信息由证果果编辑整理&#xff0c;更多认证机构信息请到证果果网站查看。找机构…...

全网招募P图高手!阿里巴巴持续训练鉴假AI

P过的证件如何鉴定为真&#xff1f;三千万网友都晒出了与梅西的合影&#xff1f;图像编辑技术的普及让人人都能P图&#xff0c;但也带来“假图”识别难题&#xff0c;甚至是欺诈问题。 为此&#xff0c;阿里安全联合华中科技大学国家防伪工程中心、国际文档分析识别方向的唯一顶…...

webrtc QOS笔记一 Neteq直方图算法浅读

webrtc QOS笔记一 Neteq直方图算法浅读 文章目录webrtc QOS笔记一 Neteq直方图算法浅读Histogram Algorithm获取目标延迟遗忘因子曲线Histogram Algorithm DelayManager::Update()->Histogram::Add() 会根据计算的iat_packet(inter arrival times, 实际包间间隔 / 打包时长…...

细分和切入点

本文重点介绍做SEO网站细分和切入点的方法&#xff1a;当我们的行业和关键词竞争性比较大的时候&#xff0c;我们可以考虑对行业或者产品做细分&#xff0c;从而找到切入点。可以按照以下三个方面进行细分。1、按城市细分例如&#xff1a;A&#xff1a;餐饮培训&#xff0c;当前…...

iOS创建Universal Link

iOS 9之前&#xff0c;一直使用的是URL Schemes技术来从外部对App进行跳转&#xff0c;但是iOS系统中进行URL Schemes跳转的时候如果没有安装App&#xff0c;会提示无法打开页面的提示。 iOS 9之后起可以使用Universal Links技术进行跳转页面&#xff0c;这是一种体验更加完美的…...

RuoYi-Vue搭建(若依)

项目简介 RuoYi-Vue基于SpringBootVue前后端分离的Java快速开发框架1.前端采用Vue、Element UI2.后端采用Spring Boot、Spring Security、Redis & Jwt3.权限认证使用Jwt&#xff0c;支持多终端认证系统4.支持加载动态权限菜单&#xff0c;多方式轻松权限控制5.高效率开发&a…...

进程组和用处

进程组&#xff1a;一个或多个进程的集合&#xff0c;进程组id是一个正整数。组长进程&#xff1a;进程组id 进程id组长进程可以创建一个进程组&#xff0c;创建该进程组的进程&#xff0c;终止了&#xff0c;只要进程组有一个进程存在&#xff0c;进程组就存在&#xff0c;与…...

Nacos集群+Nginx负载均衡

搭建Nacos集群 注意: 3个或3个以上Nacos节点才能构成集群。要求服务器内存分配最好大于6G以上&#xff08;如果不够则需修改nacos启动脚本中的默认内存配置&#xff09;根据nacos自带的mysql建库脚本建立对应数据库&#xff08;/conf/nacos-mysql.sql&#xff09;如果是三台服…...

TypeScript 学习之类型兼容

TypeScript 的类型兼容性是基于结构子类型的。 结构类型是一种只使用其成员来描述类型的方式。 interface Named {name: string; }class Person {name: string; }let p: Named; p new Person();// 赋值成功&#xff0c;因为都是结构类型&#xff0c;只要Person 类型的包含 Nam…...

Linux软件管理RPM

目录 前言 RPM软件管理程序&#xff1a;rpm RPM默认安装的路径 PRM讲解前准备工作 RPM安装&#xff08;install&#xff09; RPM查询&#xff08;query&#xff09; RPM卸载&#xff08;erase&#xff09; RPM升级与更新&#xff08;upgrade/freshen&#xff09; RPM重…...

01背包问题

背包问题的递归解决过程如下&#xff1a; 第一步明确思路 在解决问题之前&#xff0c;为描述方便&#xff0c;首先定义一些变量&#xff1a;Vi表示第 i 个物品的价值&#xff0c;Wi表示第 i 个物品的体积&#xff0c;定义V(i,j)&#xff1a;当前背包容量 j&#xff0c;前 i 个…...

14_FreeRTOS二值信号量

目录 信号量的简介 队列与信号量的对比 二值信号量 二值信号量相关API函数 实验源码 信号量的简介 信号量是一种解决同步问题的机制,可以实现对共享资源的有序访问。 假设有一个人需要在停车场停车 1.首先判断停车场是否还有空车位(判断信号量是否有资源) 2.停车场正好…...

JavaScript随手笔记---轮播图(点击切换)

&#x1f48c; 所属专栏&#xff1a;【JavaScript随手笔记】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#…...

机器人学 markdown数学公式常用语法

参考链接1 本文包含了markdown常用的数学公式&#xff0c;按照目录可查询选用 初始类 行内数学公式均用两个符号包裹行间数学公式均用两个符号包裹 行间数学公式均用两个符号包裹行间数学公式均用两个符号包裹&#xff0c;用于表示重要的、需在行间单独列出的公式 $行内数学…...

如何使用 Python 语言来编码和解码 JSON 对象

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式&#xff0c;易于人阅读和编写。 JSON 函数 使用 JSON 函数需要导入 json 库&#xff1a;import json。 函数 描述 json.dumps 将 Python 对象编码成 JSON 字符串 json.loads 将已编码的 JSON 字符串解码为 Pyth…...

【蓝桥云课】求正整数的约数个数

一、求正整数n的约数个数 方法一(常用算法)&#xff1a;从1到n逐一判断其能否整除n&#xff0c;若能整除n即为n的约数&#xff0c;否则不是n的约数。 方法二&#xff1a;从1到n\sqrt{n}n​逐一判断是否为n的约数&#xff0c;当n\sqrt{n}n​为n的约数时&#xff0c;个数加1&…...

崂山区城乡建设局网站/网站查询器

Resharper是一款很优秀的重构工具&#xff0c;已经习惯了Resharper快捷键&#xff0c;利用Resharper做重构&#xff0c;TDD开发&#xff0c;很爽。唯一缺点就是低配置机器上速度很慢&#xff0c;容易拖死VS&#xff0c; 为此我我专门把我的本本换成6G内存&#xff0c;现在感觉顺…...

wap网站制作工具/如何创建一个网址

Scala集合的mutable和immutable解释概述集合API概述概述 Scala 集合类系统地区分了可变的和不可变的集合。可变集合可以在适当的地方被更新或扩展。这意味着你可以修改&#xff0c;添加&#xff0c;移除一个集合的元素。而不可变集合类&#xff0c;相比之下&#xff0c;永远不会…...

内蒙古建设工程交易中心网站/手机百度浏览器

TimeLimitingCollector 包装其他的收集器&#xff0c;当查询超过指定时间时通过抛出TimeExceededException异常来中止搜索。通过一个被包装的收集器&#xff0c;一个时钟定时器和超时时间来构造TimeLimitingCollector对象。setBaseline(long clockTime)&#xff1a;在包…...

辽宁网站建设/详情页设计

主要软件包&#xff0c; 1. httpd-2.2.6.tar.gz 2. mysql-5.0.45-linux-i686-glibc23.tar.gz ( 这个版本是已编译好的压缩包&#xff0c;解压后稍做配置即可使用 ) 3. php-5.2.5.tar.gz 安装 php 所需的软件包&#xff08;其中 libxml2 是安装 php5 必须的 . &#xff09; 1. l…...

网站前置审批专项/国际婚恋网站排名

环境&#xff1a; 电脑&#xff1a;联想E14 系统&#xff1a;Windows 10 专业版 64位 VMware 16.0 &#xff1a;Ubuntu20.04 问题描述&#xff1a; 如何更新国内源&#xff0c;原因是安装ssh没成功 解决方案&#xff1a; 1.备份原来的源 sudo cp /etc/apt/sources.list…...

用wordpress好吗/黑龙江头条今日新闻

欢迎您戳蓝色字“工数平台”持续关注我们哟&#xff01;导言在当今中国的各个领域&#xff0c;“弯道超车”是个经常被提及的口号&#xff0c;然而常识和交规告诉我们&#xff0c;弯道不仅不能超车还得减速&#xff0c;超车极其危险。仔细解读“弯道超车”&#xff0c;其实还暗…...