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

【Linux 网络编程1】使用UDP/TCP编写套接字,多进程/多线程版本的TCP编写的套接字,将套接字封装

目录

1.学习网络编程前的一些基础知识

2.UDP(user datagram protocol)协议的特点

3.使用有UPD编写套接字

4.使用TCP编写套接字

4.2.TCP客服端 

4.3.TCP服务器端

4.4.单进程版本(没有人会使用)

4.5.多进程版本

4.6.多线程版本

5.把套接字封装


1.学习网络编程前的一些基础知识

1.1.IP地址

  • IP地址是在IP协议中, 用来标识网络中不同主机的地址(一个IP地址标识一台主机);
  • 通常使用 "点分十进制" 的字符串表示IP地址, 例如127.0.0.1 ; 用点分割的每一个数字表示一个字节, 范围是 0 - 255,就是一个字节的大小,IP地址刚好是4字节, 32位的整数;

1.2.端口号(port) 

  • 端口号是一个2字节16位的整数
  • 端口号用来标识一个进程,那么IP地址+端口号就可以标识某一台主机的某一个进程

1.3.TCP/IP四层模型 

 

1.4.网络字节序 

  • 网络字节序就是大端字节序(低位放在高地址上),使用相同的字节序便于网络间通信;

有系统提供的接口 

2.UDP(user datagram protocol)协议的特点

UDP协议是一个传输层协议

  • 无连接:没有连接,客户端发给服务器端,服务器端要先保存客户端的信息,服务器端再使用这个信息发给对应的客户端(简单地说就是需要指明发送给谁
  • 不可靠传输:只是传递数据,成功与否都不会反馈
  • 面向数据报:不能向面向字节流的TCP一样使用read和write来读写

3.使用有UPD编写套接字

3.1.服务器端

3.1.1.创建套接字

    int sock=socket(AF_INET,SOCK_DGRAM,0);//创建套接字if(sock<0){std::cerr<<"socket fail: "<<errno<<std::endl;return 1;} 

3.1.2.bind服务器 

网络字节序就是大端字节序(低位放在高地址上),使用相同的字节序便于网络间通信;

  1. 1.需要将人识别的点分十进制,字符串风格IP地址,转化为4字节整数IP.2.考虑大小端的问题

服务器不用bind一个固定的IP的原因

  1. 1.云服务器,不允许bind公网IP,另外,在一般编写也不会指明IP.2.一般主机有多个IP,如果只是bind一个IP,发给其他IP的数据就不会交给主机处理
  2. INADDR_ANY只要是发给这个主机的数据都会被处理

    struct sockaddr_in local;local.sin_family=AF_INET;local.sin_port=htons(port);//1.需要将人识别的点分十进制,字符串风格IP地址,转化为4字节整数IP.2.考虑大小端的问题//1.云服务器,不允许bind公网IP,另外,在一般编写也不会指明IP.2.一般主机有多个IP,如果只是bind一个IP,发给其他IP的数据就不会交给主机处理;//INADDR_ANY只要是发给这个主机的数据都会被处理local.sin_addr.s_addr=INADDR_ANY;if(bind(sock,(struct sockaddr*)&local,sizeof(local))<0)//bind主机{std::cerr << "bind error : " << errno << std::endl;return 2;}

3.1.3.传递接受数据

  • UDP是无连接的,需指明发给谁,也需要保存发送端的信息

    //业务逻辑char message[1024];bool quit=false;while(!quit){//保存发送端信息struct sockaddr_in peer; socklen_t len=sizeof(peer);//接受数据ssize_t s=recvfrom(sock,message,sizeof(message)-1,0,(struct sockaddr*)&peer,&len);if(s>0){message[s]=0;std::cout<<"client# "<<message<<std::endl;}else{std::cerr<<"recvfrom"<<errno<<std::endl;return 2;}//给对端发送一个你好吗std::string tm="你好吗?";std::cout<<"server to client: "<<tm<<std::endl;sendto(sock,tm.c_str(),tm.size(),0,(struct sockaddr*)&peer,len);}

 3.2.客户端

  • 客户端不需要显示bind,当传输第一个数据是会自动随机bind一个port(没有被使用的port)
#include<iostream>
#include<cerrno>
#include<string>
#include<cstdlib>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>//client serverIP serverPort
int main(int argc,char* argv[])
{if(argc!=3){std::cout<<"请按格式输入: client serverIP serverPort"<<std::endl;return 2;}int sock=socket(AF_INET,SOCK_DGRAM,0);//创建套接字if(sock<0){std::cout<<"socket create errno: "<<errno<<std::endl;return 1;}//客户端不用显示bind,OS会自动bind;//服务器端会有规划,让port是没有被占用的,让别人来访问这个port;//client正常发送数据的时候,OS会自动给你bind,采用随机端口的方式struct sockaddr_in server;server.sin_family=AF_INET;server.sin_port=htons(atoi(argv[2]));server.sin_addr.s_addr=inet_addr(argv[1]);while(1){std::string message;std::cout<<"请输入#";std::cin>>message;sendto(sock,message.c_str(),message.size(),0,(struct sockaddr*)&server,sizeof(server));struct sockaddr_in tmp;socklen_t tlen=sizeof(tmp);char buffer[1024];ssize_t s=recvfrom(sock,buffer,sizeof(buffer)-1,0,(struct sockaddr*)&tmp,&tlen);if(s>0){std::cout<<"server say#: "<<buffer<<std::endl;buffer[s]=0;   }else{std::cerr<<"recvfrom"<<errno<<std::endl;return 2;}}return 0;
}

4.使用TCP编写套接字

4.1.TCP的特点

TCP是一个传输层协议,和UDP的特点相反

  • 有连接
  • 可靠传输
  • 面向字节流

4.2.TCP客服端 

先写的客户端,因为服务器端会写多个版本

#include<iostream>
#include<stdio.h>
#include<cerrno>
#include<unistd.h>
#include<string>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>void Usage()
{std::cout<<"usage:./client server_IP server_port"<<std::endl;
}
int main(int argc,char* argv[])
{if(argc!=3){Usage();return 1;}//建立套接字int sock=socket(AF_INET,SOCK_STREAM,0);if(sock<0){std::cerr<<"socket"<<errno<<std::endl;return 2;}//自动bind//连接服务器struct sockaddr_in local;local.sin_addr.s_addr=inet_addr(argv[1]);local.sin_port=htons(atoi(argv[2]));local.sin_family=AF_INET;connect(sock,(struct sockaddr*)&local,sizeof(local));//业务逻辑while(1){char buffer[1024]={0};std::cout<<"请输入";fgets(buffer,sizeof(buffer),stdin);write(sock,buffer,sizeof(buffer));char mes[1024]={0};read(sock,mes,sizeof(mes));std::cout<<mes<<std::endl;}return 0;
}

4.3.TCP服务器端

4.3.1.创建套接字和bind服务器

  • socket的第二个参数是SOCK_STREAM,UPD是SOCK_DGRAM(datagram),TCP是SOCK_STREAM(stream,就是字节流)
//建立套接字int listen_sock=socket(AF_INET,SOCK_STREAM,0);if(listen_sock<0){std::cerr<<"socket"<<errno<<std::endl;return 1;}//bind服务器struct sockaddr_in local;local.sin_family=AF_INET;local.sin_port=htons(PORT);local.sin_addr.s_addr=INADDR_ANY;//INADDR_ANY会bind执行代码的主机if(bind(listen_sock,(struct sockaddr*)&local,sizeof(local))<0){std::cerr<<"bind"<<errno<<std::endl;return 2;}

4.3.2.listen设为聆听状态

    //listen状态listen(listen_sock,5);

 4.3.3.accept接受客户端的连接,并返回一个文件描述符

  • 因为TCP套接字是有连接的,连接成功后也是使用返回的套接字和对端进行网络通信

struct sockaddr_in tmp;
socklen_t tlen=sizeof(tmp);
//建立连接
int fd=accept(listen_sock,(struct sockaddr*)&tmp,&tlen);

4.4.单进程版本(没有人会使用)

  • 一次只能让一个客户端访问
  • 写端关闭读端读到文件结尾,再读返回0
int main()
{//...创建套接字、bind、listen都省略了,每次都一样冗余while(1){struct sockaddr_in tmp;socklen_t tlen=sizeof(tmp);//建立连接int fd=accept(listen_sock,(struct sockaddr*)&tmp,&tlen);if(fd<0){std::cerr<<"accept "<<errno<<std::endl;return 3;}std::cout<<"get a new link "<<std::endl;//1.单进程versionwhile(1){char buffer[1024]={0};ssize_t s=read(fd,buffer,sizeof(buffer));if(s>0){buffer[s]=0;std::cout<<"client to server:"<<buffer<<std::endl;std::string message;message+="server to client:你好!";//给连接的客户端发一个你好write(fd,message.c_str(),message.length());}else if(s==0){//写端关闭读端读到文件结尾,再读返回0std::cout<<"client quit!"<<std::endl;break;}else{std::cerr<<"read "<<errno<<std::endl;break;}}}
}

4.5.多进程版本

4.5.1.父进程是一个循环,他要一直接收新的客服端不能等待子进程,解决方法

  1. 父进程等待子进程,子进程创建后再创建孙子进程执行后序代码,子进程秒退等待时间可以忽略不计;下面代码

pid_t pid = fork();if(pid<0){continue;}else if(pid==0){//子进程close(listen_sock);if(fork()>0)exit(0);//子进程创建就直接退出,创建的孙子进程执行后序代码,孙子进程变成孤儿进程被1号进程领养serviceIO(fd);close(fd);exit(0);}else{//父进程close(fd);//子进程的PCB以父进程的PCB做模板初始化,不是共享的//waitpid(&pid,NULL,0);//父进程等待子进程,子进程创建后再创建孙子进程执行后序代码,子进程秒退等待时间可以忽略不计}

        2.signal(SIGCHLD,SIG_IGN);//忽略SIGCHLD信号,子进程将自动释放; 

2.关闭不用的文件描述符,父进程关闭accept返回的文件描述符,子进程关闭socket返回的文件描述符

void serviceIO(const int& fd)
{//1.单进程version,做成一个函数while(1){char buffer[1024]={0};ssize_t s=read(fd,buffer,sizeof(buffer));if(s>0){buffer[s]=0;std::cout<<"client to server:"<<buffer<<std::endl;std::string message;message+="server to client:你好!";//给连接的客户端发一个你好write(fd,message.c_str(),message.length());}else if(s==0){//写端关闭读端读到文件结尾,再读返回0std::cout<<"client quit!"<<std::endl;break;}else{std::cerr<<"read "<<errno<<std::endl;break;}}
}int main()
{//...创建套接字、bind、listen都省略了,每次都一样冗余signal(SIGCHLD,SIG_IGN);//忽略SIGCHLD信号,子进程将自动释放while(1){struct sockaddr_in tmp;socklen_t tlen=sizeof(tmp);//建立连接int fd=accept(listen_sock,(struct sockaddr*)&tmp,&tlen);std::cout<<"get a new link "<<std::endl;if(fd<0){std::cerr<<"accept "<<errno<<std::endl;return 3;}//2.多进程versionpid_t pid = fork();if(pid<0){continue;}else if(pid==0){//子进程close(listen_sock);serviceIO(fd);close(fd);exit(0);}else{//父进程close(fd);//子进程的PCB以父进程的PCB做模板初始化,不是共享的}}
}

4.6.多线程版本

  • 线程是共享PCB的,所以在线程内使用完毕关闭文件描述符即可;
  • 不等待线程可以使用线程分离的方法
void serviceIO(const int& fd)
{//1.单进程versionwhile(1){char buffer[1024]={0};ssize_t s=read(fd,buffer,sizeof(buffer));if(s>0){buffer[s]=0;std::cout<<"client to server:"<<buffer<<std::endl;std::string message;message+="server to client:你好!";//给连接的客户端发一个你好write(fd,message.c_str(),message.length());}else if(s==0){//写端关闭读端读到文件结尾,再读返回0std::cout<<"client quit!"<<std::endl;break;}else{std::cerr<<"read "<<errno<<std::endl;break;}}
}
void* HandlerRequest(void* agrs)
{pthread_detach(pthread_self());int fd=*((int*)agrs);serviceIO(fd);close(fd);//记得关闭文件描述符
}
int main()
{while(1){struct sockaddr_in tmp;socklen_t tlen=sizeof(tmp);//建立连接int fd=accept(listen_sock,(struct sockaddr*)&tmp,&tlen);std::cout<<"get a new link "<<std::endl;if(fd<0){std::cerr<<"accept "<<errno<<std::endl;return 3;}pthread_t tid;pthread_create(&tid,nullptr,HandlerRequest,(void*)&fd);}return 0;
}

5.把套接字封装

  • 使用静态是因为不用创建对象就可以使用sock::Socket()等函数;
#pragma once
#include<iostream>
#include<cstdlib>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<arpa/inet.h>namespace ns_socket{class sock{public:static int Socket(){int sock=socket(AF_INET,SOCK_STREAM,0);if(sock<0){std::cerr<<"socket"<<std::endl;exit(1);}return sock;}static void Bind(int sock,char* port){struct sockaddr_in local;local.sin_family=AF_INET;local.sin_addr.s_addr=INADDR_ANY;local.sin_port=htons(atoi(port));if(bind(sock,(struct sockaddr*)&local,sizeof(local))<0){std::cerr<<"bind"<<std::endl;exit(2);}}static void Listen(int sock){if(listen(sock,5)<0){std::cerr<<"listen"<<std::endl;exit(3);}}static int Accept(int sock) {struct sockaddr_in tmp;socklen_t tlen=sizeof(tmp);int new_sock=accept(sock,(struct sockaddr*)&tmp,&tlen);if(new_sock<0){std::cerr<<"accept"<<std::endl;exit(4);}return new_sock;  }static void Connect(int sock,char* server_ip,char* server_port){struct sockaddr_in local;local.sin_family=AF_INET;local.sin_addr.s_addr=inet_addr(server_ip);local.sin_port=htons(atoi(server_port));if(connect(sock,(struct sockaddr*)&local,sizeof(local))<0){std::cerr<<"connect"<<std::endl;exit(5);}else{std::cout<<"connet success"<<std::endl;}}};
}

相关文章:

【Linux 网络编程1】使用UDP/TCP编写套接字,多进程/多线程版本的TCP编写的套接字,将套接字封装

目录 1.学习网络编程前的一些基础知识 2.UDP(user datagram protocol)协议的特点 3.使用有UPD编写套接字 4.使用TCP编写套接字 4.2.TCP客服端 4.3.TCP服务器端 4.4.单进程版本&#xff08;没有人会使用&#xff09; 4.5.多进程版本 4.6.多线程版本 5.把套接字封装 1…...

滑动窗口求最大和最小

滑动窗口 要区分最小和最大滑窗&#xff0c;内层while循环的条件和更新结果的地方 核心&#xff1a; 关键的区别在于&#xff0c;最大滑窗是在迭代右移右边界的过程中更新结果&#xff0c;而最小滑窗是在迭代右移左边界的过程中更新结果。 最小滑窗 给定数组 nums&#xff0…...

跟ChatGPT学量化,菜鸟炒股也不怕

你是一个python资深量化开发工程师&#xff0c;请介绍量化交易的基本框架 量化交易的基本框架包括以下几个步骤&#xff1a; 数据获取&#xff1a;获取市场数据和公司财务数据等&#xff0c;可以使用API接口、爬虫等方式获取。数据清洗和预处理&#xff1a;对获取到的数据进行清…...

扬帆优配|2600亿新能源巨头狂飙!外资唱多中国:再涨15%

全国停摆的危机&#xff0c;正在迫临法国。 大停工正在将法国推向风险境地。法国政府估计&#xff0c;当地时间3月7日&#xff0c;将迸发全国大型停工游行。法国总工会宣告&#xff0c;到时将让全法国停摆。法国担任交通业务的部长级代表克莱蒙博讷正告称&#xff0c;7日将成为…...

ChatGPT技术与商业模式及产业发展布局方案

文章目录模块一&#xff1a;概念模块二&#xff1a;架构模块三&#xff1a;技术模块四&#xff1a;算力模块五&#xff1a;体验模块六&#xff1a;应用模块七&#xff1a;商业模块八&#xff1a;产业模块九&#xff1a;建议结语主要内容&#xff1a; 采用模块化教学方法&#x…...

CIMCAI port ai shipping ai artificial intelligence smart port

上海人工智能独角兽中集集团高科技中集飞瞳&#xff0c;是全球应用落地最广&#xff0c;规模最大&#xff0c;最先进的的港航人工智能高科技企业&#xff0c;工业级成熟港航人工智能产品全球规模化落地应用&#xff0c;全球前三大船公司及港口码头应用落地。上海人工智能独角兽…...

《数据解构》HashMap源码解读

&#x1f451;作者主页&#xff1a;Java冰激凌 &#x1f4d6;专栏链接&#xff1a;数据结构 目录 了解HashMap HashMap的构造 两个参数的构造方法 一个参数的构造方法 不带参数的构造方法 哈希表初始化的长度 HashMap源码中的成员 Pt Get 了解HashMap 首先我们要明…...

Databend 开源周报 第 83 期

Databend 是一款现代云数仓。专为弹性和高效设计&#xff0c;为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务&#xff1a;https://app.databend.com 。Whats New探索 Databend 本周新进展&#xff0c;遇到更贴近你心意的 Databend 。Support for WebHDFSHDFS 是大数…...

Spring | 基础

1. IOC和DI IOC&#xff1a;控制反转&#xff0c;其思想是反转资源获取的方向&#xff0c;传统的资源查找方式要求组件向容器发起请求查找资源&#xff0c;作为回应&#xff0c;容器适时的返回资源。而应用了 IOC 之后&#xff0c;则是**容器主动地将资源推送给它所管理的组件…...

windows7安装sql server 2000安装步骤 及安装过程中遇到的问题和解决方式

提示&#xff1a;文章写完后windows7安装sql server 2000安装步骤 及安装过程中遇到的问题和解决方式&#xff0c; 文章目录一、ms sql server 2000是什么&#xff1f;版本简介&#xff1a;**特点&#xff1a;****优点&#xff1a;**二、步骤1.下载安装包及Sq4补丁包2.安装 ms …...

Python 开发-批量 FofaSRC 提取POC 验证

数据来源 学习内容和目的&#xff1a; ---Request 爬虫技术&#xff0c;lxml 数据提取&#xff0c;异常护理&#xff0c;Fofa 等使用说明---掌握利用公开或 0day 漏洞进行批量化的收集及验证脚本开发Python 开发-某漏洞 POC 验证批量脚本---glassfish存在任意文件读取在默认4…...

Linux系统中部署软件

目录 1.Mysql 2.Redis 3.ZooKeeper 声明 致谢 1.Mysql 参考&#xff1a;CentOS7安装MySQL 补充&#xff1a; ① 执行&#xff1a;rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022 再执行&#xff1a;yum -y install mysql-community-server ② mysql…...

PHP常用框架介绍与比较

HP是一种广泛应用于Web开发的编程语言。随着互联网的快速发展,PHP的应用场景变得越来越广泛,从简单的网站到复杂的Web应用程序都可以使用PHP来开发。为了更好地组织和管理PHP代码,开发人员经常会使用框架来提高开发效率和代码质量。 本文将介绍一些常用的PHP框架,并进行简…...

Umi + React + Ant Design Pro 项目实践(一)—— 项目搭建

学习一下 Umi、 Ant Design 和 Ant Design Pro 从 0 开始创建一个简单应用。 首先&#xff0c;新建项目目录&#xff1a; 在项目目录 D:\react\demo 中&#xff0c;安装 Umi 脚手架&#xff1a; yarn create umi # npm create umi安装成功&#xff1a; 接下来&#xff0c;…...

MySQL知识点总结(1)

目录 1、sql、DB、DBMS分别是什么&#xff0c;他们之间的关系&#xff1f; 2、什么是表&#xff1f; 3、SQL语句怎么分类呢&#xff1f; 4、导入数据 5、什么是sql脚本呢&#xff1f; 6、删除数据库 7、查看表结构 8、表中的数据 10、查看创建表的语句 11、简单的查询…...

day45第九章动态规划(二刷)

今日任务 70.爬楼梯(进阶)322.零钱兑换279.完全平方数 70.爬楼梯(进阶) 题目链接&#xff1a; https://leetcode.cn/problems/climbing-stairs/description/ 题目描述&#xff1a; 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不…...

第十四届蓝桥杯第三期模拟赛原题与详解

​​​​​​​ 文章目录 一、填空题 1、1 找最小全字母十六进制数 1、1、1 题目描述 1、1、2 题解关键思路与解答 1、2 给列命名 1、2、1 题目描述 1、2、2 题解关键思路与解答 1、3 日期相等 1、3、1 题目描述 1、3、2 题解关键思路与解答 1、4 乘积方案数 1、4、1 题目描…...

client打包升级

目录 前言 一、client如何打包升级&#xff1f; 二、使用步骤 1.先进行改版本 2.执行打包升级命令 总结 前言 本文章主要记录一下&#xff0c;日常开发中&#xff0c;常需要进行打包升级的步骤。 一、client如何打包升级&#xff1f; # 升级发布版本 ## 修改版本 * 父p…...

Blazor_WASM之3:项目结构

Blazor_WASM之3&#xff1a;项目结构 Blazor WebAssembly项目模板可选两种&#xff0c;Blazor WebAssemblyAPP及Blazor WebAssemblyAPP-Empty 如果使用Blazor WebAssemblyAPP模板&#xff0c;则应用将填充以下内容&#xff1a; 一个 FetchData 组件的演示代码&#xff0c;该…...

OperWrt 包管理系统02

文章目录 OperWrt 包管理系统OPKG简介OPKG的工作原理OPKG命令介绍软件包的更新、安装、卸载和升级等功能软件包的信息查询OPKG配置文件说明OPKG包结构(.ipk)OPKG演示案例OperWrt 包管理系统 OPKG简介 OPKG(Open/OpenWrt Package)是一个轻量快速的软件包管理系统,是 IPKG…...

python打卡day49

知识点回顾&#xff1a; 通道注意力模块复习空间注意力模块CBAM的定义 作业&#xff1a;尝试对今天的模型检查参数数目&#xff0c;并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩

目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

【机器视觉】单目测距——运动结构恢复

ps&#xff1a;图是随便找的&#xff0c;为了凑个封面 前言 在前面对光流法进行进一步改进&#xff0c;希望将2D光流推广至3D场景流时&#xff0c;发现2D转3D过程中存在尺度歧义问题&#xff0c;需要补全摄像头拍摄图像中缺失的深度信息&#xff0c;否则解空间不收敛&#xf…...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

P3 QT项目----记事本(3.8)

3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...

均衡后的SNRSINR

本文主要摘自参考文献中的前两篇&#xff0c;相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程&#xff0c;其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt​ 根发送天线&#xff0c; n r n_r nr​ 根接收天线的 MIMO 系…...

以光量子为例,详解量子获取方式

光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学&#xff08;silicon photonics&#xff09;的光波导&#xff08;optical waveguide&#xff09;芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中&#xff0c;光既是波又是粒子。光子本…...

【Linux】自动化构建-Make/Makefile

前言 上文我们讲到了Linux中的编译器gcc/g 【Linux】编译器gcc/g及其库的详细介绍-CSDN博客 本来我们将一个对于编译来说很重要的工具&#xff1a;make/makfile 1.背景 在一个工程中源文件不计其数&#xff0c;其按类型、功能、模块分别放在若干个目录中&#xff0c;mak…...

Xcode 16 集成 cocoapods 报错

基于 Xcode 16 新建工程项目&#xff0c;集成 cocoapods 执行 pod init 报错 ### Error RuntimeError - PBXGroup attempted to initialize an object with unknown ISA PBXFileSystemSynchronizedRootGroup from attributes: {"isa">"PBXFileSystemSynchro…...

使用python进行图像处理—图像变换(6)

图像变换是指改变图像的几何形状或空间位置的操作。常见的几何变换包括平移、旋转、缩放、剪切&#xff08;shear&#xff09;以及更复杂的仿射变换和透视变换。这些变换在图像配准、图像校正、创建特效等场景中非常有用。 6.1仿射变换(Affine Transformation) 仿射变换是一种…...