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

《TCP/IP网络编程》阅读笔记--基于TCP的服务器端/客户端

目录

1--TCP/IP协议栈

2--TCP服务器端默认函数调用顺序

3--TCP客户端的默认函数调用顺序

4--Linux实现迭代回声服务器端/客户端

5--Windows实现迭代回声服务器端/客户端

6--TCP原理

7--Windows实现计算器服务器端/客户端


1--TCP/IP协议栈

        TCP/IP协议栈共分 4 层,可以理解为数据收发分成了 4 个层次化过程;

链路层:

        链路层是物理链接领域标准化的结果,专门定义LAN、WAN、MAN等网络标准;

IP层:

        IP层用于解决数据传输过程中路径的选择问题;

TCP/IP层:

        即传输层,用于解决数据传输的问题(数据顺序、可靠性等);

应用层:

        程序员根据数据传输规则,编写规定的程序(例如Socket)来实现数据传输;

2--TCP服务器端默认函数调用顺序

        一般 TCP 服务器端调用默认函数的顺序如下:socket() 创建 Socket → bind() 分配Socket 地址 → listen() 等待连接请求状态 → accept() 允许连接 → read()/write() 数据交换 → close() 断开连接;

        调用 listen() 函数进入等待连接请求状态,只有服务器端调用了 listen() 函数,客户端才能进入可发出连接请求的状态;

#include <sys/socket.h>int listen(int sock, int backlog); // 成功时返回 0, 失败时返回 -1;// sock 表示希望进入等待连接请求状态的Socket的文件描述符
// backlog 表示连接请求等待队列的长度,即最多可以使多少个连接请求进入队列

        服务器端调用 accept() 函数来受理客户端的连接请求,即受理等待队列中待处理的客户端连接请求;

#include <sys/socket.h>int accept(int sock, struct sockaddr* addr, socklen_t* addrlen);
// 成功时返回创建的Socket的文件描述符,失败时返回-1

3--TCP客户端的默认函数调用顺序

        一般 TCP 客户端调用默认函数的顺序如下:socket() 创建 Socket → connect() 请求连接 → read()/write() 交换数据 → close() 断开连接;

        在服务器端调用 listen() 函数创建连接请求等待队列后,客户端可通过调用 connect() 函数来请求连接;

#include <sys/socket.h>int connect(int sock, struct sockaddr* servaddr, socklen_t addrlen);// sock 表示客户端socket的文件描述符
// servaddr 保存了目标服务器端地址信息
// addrlen 第二个结构体参数 servaddr 的地址变量长度,以字节为单位

4--Linux实现迭代回声服务器端/客户端

服务器端:

// gcc echo_server.c -o echo_server
// ./echo_server 9190#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>#define BUF_SIZE 1024
void error_handling(char *message){fputs(message, stderr);fputc('\n', stderr);exit(1);
}int main(int argc, char *argv[]){int serv_sock, clnt_sock;char message[BUF_SIZE];int str_len, i;struct sockaddr_in serv_adr, clnt_adr;socklen_t clnt_adr_sz;if(argc != 2){printf("Usage : %s <port>\n", argv[0]);exit(1);}serv_sock = socket(PF_INET, SOCK_STREAM, 0);if(serv_sock == -1){error_handling("socket() error");}memset(&serv_adr, 0, sizeof(serv_adr));serv_adr.sin_family = AF_INET;serv_adr.sin_addr.s_addr = htonl(INADDR_ANY);serv_adr.sin_port = htons(atoi(argv[1]));if(bind(serv_sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr)) == -1){error_handling("bind() error");}if(listen(serv_sock, 5) == -1){error_handling("listen() error");}clnt_adr_sz = sizeof(clnt_adr);for(i = 0; i < 5; i++){clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_adr, &clnt_adr_sz);if(clnt_sock == -1){error_handling("accept() error");}else{printf("Connected client %d \n", i+1);}while((str_len = read(clnt_sock, message, BUF_SIZE)) != 0){write(clnt_sock, message, str_len);}close(clnt_sock);}close(serv_sock);return 0;
}

客户端:

// gcc echo_client.c -o echo_client
// ./echo_client 127.0.0.1 9190#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>#define BUF_SIZE 1024void error_handling(char *message){fputs(message, stderr);fputc('\n', stderr);exit(1);
}int main(int argc, char *argv[]){int sock;char message[BUF_SIZE];int str_len;struct sockaddr_in serv_adr;if(argc != 3){printf("Usage : %s <IP> <port>\n", argv[0]);exit(1);}sock = socket(PF_INET, SOCK_STREAM, 0);if(sock == -1){error_handling("socket() error");}memset(&serv_adr, 0, sizeof(serv_adr));serv_adr.sin_family = AF_INET;serv_adr.sin_addr.s_addr = inet_addr(argv[1]);serv_adr.sin_port = htons(atoi(argv[2]));if(connect(sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr)) == -1){error_handling("connect() error!");}else{puts("Connected.......");}while(1){fputs("Input message(Q to quit): ", stdout);fgets(message, BUF_SIZE, stdin);if(!strcmp(message, "q\n") || !strcmp(message, "Q\n")){break;}write(sock, message, strlen(message));str_len = read(sock, message, BUF_SIZE-1);message[str_len] = 0;printf("Message from server: %s", message);}close(sock);return 0;
}   

运行结果:

5--Windows实现迭代回声服务器端/客户端

服务器端:

// gcc echo_server_win.c -o echo_server_win -lwsock32
// echo_server_win 9190#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>#define BUF_SIZE 1024void ErrorHandling(char *message){fputs(message, stderr);fputc('\n', stderr);exit(1);
}int main(int argc, char *argv[]){WSADATA wsaData;SOCKET hServSock, hClntSock;char message[BUF_SIZE];int strLen, i;SOCKADDR_IN servAdr, clntAdr;int clntAdrSize;if(argc != 2){printf("Usage : %s <port>\n", argv[0]);exit(1);}if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){ErrorHandling("WSAStartup() error!");}hServSock = socket(PF_INET, SOCK_STREAM, 0);if(hServSock == INVALID_SOCKET){ErrorHandling("socket() error");}memset(&servAdr, 0, sizeof(servAdr));servAdr.sin_family = AF_INET;servAdr.sin_addr.s_addr = htonl(INADDR_ANY);servAdr.sin_port = htons(atoi(argv[1]));if(bind(hServSock, (SOCKADDR*)&servAdr, sizeof(servAdr)) == SOCKET_ERROR){ErrorHandling("bind() error");}if(listen(hServSock, 5) == SOCKET_ERROR){ErrorHandling("listen() error");}clntAdrSize = sizeof(clntAdr);for(int i = 0; i < 5; i++){hClntSock = accept(hServSock, (SOCKADDR*)&clntAdr, &clntAdrSize);if(hClntSock == -1){ErrorHandling("accept() error");}else{printf("Connected client %d \n", i + 1);}while((strLen = recv(hClntSock, message, BUF_SIZE, 0)) != 0){send(hClntSock, message, strLen, 0);}closesocket(hClntSock);}closesocket(hServSock);WSACleanup();return 0;
}

客户端:

// gcc echo_client_win.c -o echo_client_win -lwsock32
// echo_client_win 127.0.0.1 9190#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>#define BUF_SIZE 1024void ErrorHandling(char *message){fputs(message, stderr);fputc('\n', stderr);exit(1);
}int main(int argc, char *argv[]){WSADATA wsaData;SOCKET hSocket;char message[BUF_SIZE];int strLen;SOCKADDR_IN servAdr;if(argc != 3){printf("Usage: %s <IP> <port>\n", argv[0]);exit(1);}if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){ErrorHandling("WSAStartup() error!");}hSocket = socket(PF_INET, SOCK_STREAM, 0);if(hSocket == INVALID_SOCKET){ErrorHandling("socket() error");}memset(&servAdr, 0, sizeof(servAdr));servAdr.sin_family = AF_INET;servAdr.sin_addr.s_addr = inet_addr(argv[1]);servAdr.sin_port = htons(atoi(argv[2]));if(connect(hSocket, (SOCKADDR*)&servAdr, sizeof(servAdr)) == SOCKET_ERROR){ErrorHandling("connect() error!");}else{puts("Connected........");}while(1){fputs("Input message(Q to quit): ", stdout);fgets(message, BUF_SIZE, stdin);if(!strcmp(message, "q\n") || !strcmp(message, "Q\n")){break;}send(hSocket, message, strlen(message), 0);strLen = recv(hSocket, message, BUF_SIZE - 1, 0);message[strLen] = 0;printf("Message from server: %s", message);}closesocket(hSocket);WSACleanup();return 0;
}

测试结果:

6--TCP原理

I/O缓冲:

        当调用 write() 函数后并不会立即传输数据,而是将数据移至输出缓冲;

        同样当调用 read() 函数后也并不会马上接收数据,而是将数据移至输入缓冲;

        TCP会控制数据流,使用滑动窗口协议(参考博主之前的笔记:TCP流量控制)来限制数据传输不会超过输入缓冲的大小;

TCP 协议使用三次握手来建立连接,使用四次挥手来断开连接;(具体分析参考书中图解)

7--Windows实现计算器服务器端/客户端

服务器端:

// gcc op_server_win.c -o op_server_win -lwsock32
// op_server_win 9190#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>#define BUF_SIZE 1024
#define OPSZ 4void ErrorHandling(char *message){fputs(message, stderr);fputc('\n', stderr);exit(1);
}int calculate(int opnum, int opnds[], char op){int result = opnds[0], i;switch(op){case '+':for(i = 1; i < opnum; i++) result += opnds[i];break;case '-':for(i = 1; i < opnum; i++) result -= opnds[i];break;case '*':for(i = 1; i < opnum; i++) result *= opnds[i];break;}return result;
}int main(int argc, char* argv[]){WSADATA wsaData;SOCKET hServSock, hClntSock;char opinfo[BUF_SIZE];int result, opndCnt, i;int recvCnt, recvLen;SOCKADDR_IN servAdr, clntAdr;int clntAdrSize;if(argc != 2){printf("Usage: %s <port>\n", argv[0]);exit(1);}if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){ErrorHandling("WSAStartup() error!");}hServSock = socket(PF_INET, SOCK_STREAM, 0);if(hServSock == INVALID_SOCKET){ErrorHandling("socket() error!");}memset(&servAdr, 0, sizeof(servAdr));servAdr.sin_family = AF_INET;servAdr.sin_addr.s_addr = htonl(INADDR_ANY);servAdr.sin_port = htons(atoi(argv[1]));if(bind(hServSock, (SOCKADDR*)&servAdr, sizeof(servAdr)) == SOCKET_ERROR){ErrorHandling("bind() error");}if(listen(hServSock, 5) == SOCKET_ERROR){ErrorHandling("listen() error");}clntAdrSize = sizeof(clntAdr);for(int i = 0; i < 5; i++){opndCnt = 0;hClntSock = accept(hServSock, (SOCKADDR*)&clntAdr, &clntAdrSize);recv(hClntSock, (char*)&opndCnt, 1, 0); // recv one byterecvLen = 0;while((opndCnt * OPSZ + 1) > recvLen){recvCnt = recv(hClntSock, &opinfo[recvLen], BUF_SIZE - 1, 0);recvLen += recvCnt;}result = calculate(opndCnt, (int*)opinfo, opinfo[recvLen - 1]);send(hClntSock, (char*)&result, sizeof(result), 0);closesocket(hClntSock);}closesocket(hServSock);WSACleanup();return 0;
}

客户端:

// gcc op_client_win.c -o op_client_win -lwsock32
// op_client_win 127.0.0.1 9190#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>#define BUF_SIZE 1024
#define RLT_SIZE 4
#define OPSZ 4void ErrorHandling(char *message){fputs(message, stderr);fputc('\n', stderr);exit(1);
}int main(int argc, char* argv[]){WSADATA wsaData;SOCKET hSocket;char opmsg[BUF_SIZE];int result, opndCnt, i;SOCKADDR_IN servAdr;if(argc != 3){printf("Usage : %s <IP> <port>\n", argv[0]);exit(1);}if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){ErrorHandling("WSAStartup() error!");}hSocket = socket(PF_INET, SOCK_STREAM, 0);if(hSocket == INVALID_SOCKET){ErrorHandling("socket() error!");}memset(&servAdr, 0, sizeof(servAdr));servAdr.sin_family = AF_INET;servAdr.sin_addr.s_addr = inet_addr(argv[1]);servAdr.sin_port = htons(atoi(argv[2]));if(connect(hSocket, (SOCKADDR*)&servAdr, sizeof(servAdr)) == SOCKET_ERROR){ErrorHandling("connect() error!");}else{puts("Connected........");}fputs("Operand count: ", stdout);scanf("%d", &opndCnt);opmsg[0] = (char)opndCnt; // one bytefor(i = 0; i < opndCnt; i++){printf("Operand %d: ", i + 1);scanf("%d", (int*)&opmsg[i*OPSZ + 1]);}fgetc(stdin);fputs("Operator: ", stdout);scanf("%c", &opmsg[opndCnt * OPSZ + 1]); // one bytesend(hSocket, opmsg, opndCnt * OPSZ + 2, 0);recv(hSocket, (char*)&result, RLT_SIZE, 0);printf("Operation result: %d \n", result);closesocket(hSocket);WSACleanup();return 0;
}

运行结果:

相关文章:

《TCP/IP网络编程》阅读笔记--基于TCP的服务器端/客户端

目录 1--TCP/IP协议栈 2--TCP服务器端默认函数调用顺序 3--TCP客户端的默认函数调用顺序 4--Linux实现迭代回声服务器端/客户端 5--Windows实现迭代回声服务器端/客户端 6--TCP原理 7--Windows实现计算器服务器端/客户端 1--TCP/IP协议栈 TCP/IP协议栈共分 4 层&#xf…...

【每日一题】43. 字符串相乘

43. 字符串相乘 - 力扣&#xff08;LeetCode&#xff09; 给定两个以字符串形式表示的非负整数 num1 和 num2&#xff0c;返回 num1 和 num2 的乘积&#xff0c;它们的乘积也表示为字符串形式。 注意&#xff1a;不能使用任何内置的 BigInteger 库或直接将输入转换为整数。 示例…...

机器学习——K最近邻算法(KNN)

机器学习——K最近邻算法&#xff08;KNN&#xff09; 文章目录 前言一、原理二、距离度量方法2.1. 欧氏距离2.2. 曼哈顿距离2.3. 闵可夫斯基距离2.4. 余弦相似度2.5. 切比雪夫距离2.6. 马哈拉诺比斯距离2.7. 汉明距离 三、在MD编辑器中输入数学公式&#xff08;额外&#xff0…...

同步FIFO的verilog实现(1)——计数法

一、FIFO概述 1、FIFO的定义 FIFO是英文First-In-First-Out的缩写&#xff0c;是一种先入先出的数据缓冲器&#xff0c;与一般的存储器的区别在于没有地址线&#xff0c; 使用起来简单&#xff0c;缺点是只能顺序读写数据&#xff0c;其数据地址由内部读写指针自动加1完成&…...

python正则表达式笔记1

最近工作中经常用到正则表达式处理数据&#xff0c;慢慢发现了正则表达式的强大功能&#xff0c;尤其在数据处理工作中&#xff0c;记录下来分享给大家。 一、 正则表达式语法介绍 正则表达式&#xff08;或 RE&#xff09;指定了一组与之匹配的字符串&#xff1b;模块内的函…...

YOLO目标检测——口罩规范佩戴数据集+已标注xml和txt格式标签下载分享

实际项目应用&#xff1a;目标检测口罩佩戴检测数据集的应用场景涵盖了公共场所监控、疫情防控管理、安全管理与控制以及人员统计和分析等领域。这些应用场景可以帮助相关部门和机构更好地管理口罩佩戴情况&#xff0c;提高公共卫生和安全水平&#xff0c;保障人们的健康和安全…...

Android 13 - Media框架(9)- NuPlayer::Decoder

这一节我们将了解 NuPlayer::Decoder&#xff0c;学习如何将 MediaCodec wrap 成一个强大的 Decoder。这一节会提前讲到 MediaCodec 相关的内容&#xff0c;如果看不大懂可以先跳过此篇。原先觉得 Decoder 部分简单&#xff0c;越读越发现自己的无知&#xff0c;Android 源码真…...

23.09.5 《CLR via C#》 笔记5

第六章 类型和成员基础 类型可以定义0或多个以下成员&#xff1a;常量、字段、实例构造器、类型构造器、方法、操作符重载、转换操作符、属性、事件、类型类型的可见性分为public和internal(默认)C#中&#xff0c;成员的可访问性分为private、protected、internal、protected …...

laravel部署api项目遇到问题总结

laravel线上部署问题 一、Ubuntu远程Mysql 61“Connection refused”二、Ubuntu更新php8三、线上部署Permission denied3.1、部署完之后访问域名出现报错&#xff1a;3.2、The /bootstrap/cache directory must be present and writable. 四、图片访问404五、git部署线上文件 一…...

lintcode 1646 · 合法组合【字符串DFS, vip 中等 好题】

题目 https://www.lintcode.com/problem/1646 给一个单词s,和一个字符串集合str。这个单词每次去掉一个字母&#xff0c;直到剩下最后一个字母。求验证是否存在一种删除的顺序&#xff0c;这个顺序下所有的单词都在str中。例如单词是’abc’&#xff0c;字符串集合是{‘a’,’…...

【多线程】线程安全 问题

线程安全 问题 一. 线程不安全的典型例子二. 线程安全的概念三. 线程不安全的原因1. 线程调度的抢占式执行2. 修改共享数据3. 原子性4. 内存可见性5. 指令重排序 一. 线程不安全的典型例子 class ThreadDemo {static class Counter {public int count 0;void increase() {cou…...

【用unity实现100个游戏之11】复刻经典消消乐游戏

文章目录 前言开始项目开始一、方块网格生成二、方块交换三、添加交换的动画效果四、水平消除检测五、垂直消除检测六、完善删除功能七、效果优化&#xff08;移动方块后再进行消除检测&#xff09;八、方块下落十、方块填充十一、后续 源码参考完结 前言 欢迎来到经典消消乐游…...

若依cloud 修改包名等

一、项目的项目名。 先改pom 然后在重命名文件 1、 修改主pom.xml <artifactId>ruoyi-api</artifactId> 缓存 <artifactId>zxf-api</artifactId> <groupId>com.ruoyi</groupId> <groupId>com.zhixiaofeng</groupId> 2、…...

健康系统练习

健康系统 项目建构&#xff1a; 前后端分离&#xff0c;前端vue3&#xff0c;后端Java&#xff0c;springboot做跨域处理&#xff0c;前端将在vscode中 的tomcat下部署&#xff0c;后端将在ideal中集成的tomcat中部署 创建项目工程在ideal中直接选用springi…创建&#xff0c…...

网络协议从入门到底层原理学习(一)—— 简介及基本概念

文章目录 网络协议从入门到底层原理学习&#xff08;一&#xff09;—— 简介及基本概念一、简介1、网络协议的定义2、网络协议组成要素3、广泛的网络协议类型网络通信协议网络安全协议网络管理协议 4、网络协议模型对比图 二、基本概念1、网络互连模型2、计算机之间的通信基础…...

centos密码过期导致navicat无法通过SSH登录阿里云RDS问题

具体错误提示&#xff1a;2013 - Lost connection to server at "hand hake: reading initial communication packet, system error: 0 解决办法&#xff1a;更新SSH服务器密码...

对于pytorch和对应pytorch网站的探索

一、关于网站上面的那个教程: 适合PyTorch小白的官网教程&#xff1a;Learning PyTorch With Examples - 知乎 (zhihu.com) 这个链接也是一样的&#xff0c; 总的来说&#xff0c;里面讲了这么一件事: 如果没有pytorch的分装好的nn.module用来继承的话&#xff0c;需要设计…...

和AI聊天:动态规划

动态规划 动态规划&#xff08;Dynamic Programming&#xff0c;简称 DP&#xff09;是一种常用于优化问题的算法。它解决的问题通常具有重叠子问题和最优子结构性质&#xff0c;可以通过将问题分解成相互依赖的子问题来求解整个问题的最优解。 动态规划算法主要分为以下几个步…...

微信小程序——使用插槽slot快捷开发

微信小程序的插槽&#xff08;slot&#xff09;是一种组件化的技术&#xff0c;用于在父组件中插入子组件的内容。通过插槽&#xff0c;可以将父组件中的一部分内容替换为子组件的内容&#xff0c;实现更灵活的组件复用和定制。 插槽的使用步骤如下&#xff1a; 在父组件的wx…...

大数据技术之Hadoop:使用命令操作HDFS(四)

目录 一、创建文件夹 二、查看指定目录下的内容 三、上传文件到HDFS指定目录下 四、查看HDFS文件内容 五、下载HDFS文件 六、拷贝HDFS文件 七、HDFS数据移动操作 八、HDFS数据删除操作 九、HDFS的其他命令 十、hdfs web查看目录 十一、HDFS客户端工具 11.1 下载插件…...

基于大模型的 UI 自动化系统

基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

React Native 导航系统实战(React Navigation)

导航系统实战&#xff08;React Navigation&#xff09; React Navigation 是 React Native 应用中最常用的导航库之一&#xff0c;它提供了多种导航模式&#xff0c;如堆栈导航&#xff08;Stack Navigator&#xff09;、标签导航&#xff08;Tab Navigator&#xff09;和抽屉…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》

在注意力分散、内容高度同质化的时代&#xff0c;情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现&#xff0c;消费者对内容的“有感”程度&#xff0c;正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中&#xff0…...

多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验

一、多模态商品数据接口的技术架构 &#xff08;一&#xff09;多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如&#xff0c;当用户上传一张“蓝色连衣裙”的图片时&#xff0c;接口可自动提取图像中的颜色&#xff08;RGB值&…...

自然语言处理——Transformer

自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效&#xff0c;它能挖掘数据中的时序信息以及语义信息&#xff0c;但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN&#xff0c;但是…...

CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云

目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...

QT: `long long` 类型转换为 `QString` 2025.6.5

在 Qt 中&#xff0c;将 long long 类型转换为 QString 可以通过以下两种常用方法实现&#xff1a; 方法 1&#xff1a;使用 QString::number() 直接调用 QString 的静态方法 number()&#xff0c;将数值转换为字符串&#xff1a; long long value 1234567890123456789LL; …...

HDFS分布式存储 zookeeper

hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架&#xff0c;允许使用简单的变成模型跨计算机对大型集群进行分布式处理&#xff08;1.海量的数据存储 2.海量数据的计算&#xff09;Hadoop核心组件 hdfs&#xff08;分布式文件存储系统&#xff09;&a…...

在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案

这个问题我看其他博主也写了&#xff0c;要么要会员、要么写的乱七八糟。这里我整理一下&#xff0c;把问题说清楚并且给出代码&#xff0c;拿去用就行&#xff0c;照着葫芦画瓢。 问题 在继承QWebEngineView后&#xff0c;重写mousePressEvent或event函数无法捕获鼠标按下事…...

排序算法总结(C++)

目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指&#xff1a;同样大小的样本 **&#xff08;同样大小的数据&#xff09;**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...