0724,select +tcp 聊天室喵

news2024/12/27 10:08:29

目录

TCP协议喵

723__01:使用select实现一个基于UDP的一对一即时聊天程序。

001:

002:  TIMEWAI  OR  BUG 

721作业:

01:在一对一聊天的基础上,使用select实现一对多的回显服务。(回显服务即接收到客户端发送的数据后,再回复给客户端)

一对一的喵:

 一对多的服务器喵:

02:使用select编写聊天室程序:客户端和服务端使用tcp通信;服务端可以处理新客户端的连接和转发消息;客户端可以连入服务端并发送消息。

TCP协议喵

struct sockaddr
struct sockaddr_in  -->   struct in_addr
struct hostent 

htonl()   htons()   ntohl()   ntohs()
int inet_aton(const char* cp,struct in_addr * inp); 
in_addr_t inet_addr(const char* cp);                      
const char* inet_ntop(int af,const void* src,char* dst,socklen_t size);
struct hostent * gethostbyname(const char* name);

client :socket——connect——recv/send——close      (one fd)
server:socket——bind——listen——accept——recv/send——close
        (listendfd)             (peerfd)

int socket (int domain,int type,int protocol);
int bind (int sockfd,const struct sockaddr* addr ,socklen_t addrlen);
int listen (int sockfd,int backlog);
int connect  (int sockfd,const struct sockaddr*addr, socklen_t addrlen);
int accept (int sockfd,struct sockaddr* addr, socklen_t addrlen);
ssize_t recv ( int sockfd,void* buf,size_t buf,int flags);
ssize_t send( int sockfd,void* buf,size_t buf,int flags);

int setsockopt(int sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
                          int level ,int opname,const void* optval,socklen_t optlen

靓仔不想抄代码了呜呜,好困 

————————client :
socket
connect
while(1)
close
————————server :
socket
bind
listen
accept
send     //send是阻塞式函数
close




//第一次send可以正常执行,此时因为连接已经断开了,服务器会收到一个RST报文
//第二次send时,服务器会收到一个SIGPIPE信号 ,该信号的默认处理方式是终结进程。
//总结:client的连接关闭,会导致服务器进程奔溃,是一个不能接受的情况,因为服务器要服务其他的客户端。
————————client :
socket
connect
recv
close
————————server :
socket
bind
listen
accept
send    sleep()   send     //服务器往一个已经断开了的连接上继续发送数据,会造成什么影响?      
close



//数据在发送时是字节流,不是一个个的数据包
//数据之间是没有边界的概念  =》 TCP粘包问题

————————client :         
socket
connect
recv    recv
close
————————server :
socket
bind
listen
accept
send   send           
close




//recv的返回值为0的情况

————————client :         
socket
connect
recv    recv
close
————————server :
socket
bind
listen
accept
send      close

723__01:使用select实现一个基于UDP的一对一即时聊天程序。

001:
#include <func.h>
#define IP "192.168.235.128"
#define PORT1 8080
#define PORT2 8081

struct sockaddr* addr_create(const char* ip,int  port ){

    struct sockaddr_in* addr=(struct sockaddr_in*)malloc(sizeof(struct sockaddr_in));
    memset(addr,0,sizeof(*addr));
    addr->sin_family=AF_INET;
    addr->sin_port=htons(port);
    addr->sin_addr.s_addr=inet_addr(ip);
    return (struct sockaddr*)addr;
}

int main()
{
    struct sockaddr* addr=addr_create(IP,PORT1);
    struct sockaddr* addr1=addr_create(IP,PORT2);

    int sockfd=socket(AF_INET,SOCK_DGRAM,0);
    if(sockfd==-1){error(1,errno,"socket");}

    //addr1暴露一下?
    int err=bind(sockfd,addr1,sizeof(*addr));
    if(err==-1){error(1,errno,"bind");}

    int epfd=epoll_create1(0);
    struct epoll_event epev;
    epev.events=EPOLLIN;
    epev.data.fd=sockfd;
    epoll_ctl(epfd,EPOLL_CTL_ADD,sockfd,&epev);
    epev.data.fd=STDIN_FILENO;//标准输入的文件描述符,通常为 0
    epoll_ctl(epfd,EPOLL_CTL_ADD,STDIN_FILENO,&epev);

    struct epoll_event epev_arr[2];
    char buff[4096];


    while(1){
        int num=epoll_wait(epfd,epev_arr,2,-1);
        for(int i=0;i<num;i++){
            int fd=epev_arr[i].data.fd;
            if(fd==STDIN_FILENO){
                fgets(buff,4096,stdin);
                //给addr发消息
                sendto(sockfd,buff,strlen(buff)+1,0,addr,sizeof(struct sockaddr));
            }
            if(fd==sockfd){
                recvfrom(sockfd,buff,4096,0,NULL,NULL);
                printf("REC::%s\n",buff);
            }
        }
    }

    close(sockfd);
    return 0;
}
002:  TIMEWAI  OR  BUG 
#include <func.h>
#define IP "192.168.235.128"
#define IP1 "42.194.149.92"
#define PORT1 8082
#define PORT2 13332

struct sockaddr* addr_create(const char* ip,int  port ){

    struct sockaddr_in* addr=(struct sockaddr_in*)malloc(sizeof(struct sockaddr_in));
    memset(addr,0,sizeof(*addr));
    addr->sin_family=AF_INET;
    addr->sin_port=htons(port);
    addr->sin_addr.s_addr=inet_addr(ip);
    return (struct sockaddr*)addr;
}

int main()
{
    struct sockaddr* addr=addr_create(IP,PORT1);
    struct sockaddr* addr1=addr_create(IP1,PORT2);

    int sockfd=socket(AF_INET,SOCK_DGRAM,0);
    if(sockfd==-1){error(1,errno,"socket");}

    //addr暴露一下
    /* int err=bind(sockfd,addr,sizeof(*addr)); */
    /* if(err==-1){error(1,errno,"bind");} */

    int epfd=epoll_create1(0);
    struct epoll_event epev;
    epev.events=EPOLLIN;
    epev.data.fd=sockfd;
    epoll_ctl(epfd,EPOLL_CTL_ADD,sockfd,&epev);
    epev.data.fd=STDIN_FILENO;//标准输入的文件描述符,通常为 0
    epoll_ctl(epfd,EPOLL_CTL_ADD,STDIN_FILENO,&epev);

    struct epoll_event epev_arr[2];
    char buff[4096];


    while(1){
        int num=epoll_wait(epfd,epev_arr,2,-1);
        for(int i=0;i<num;i++){
            int fd=epev_arr[i].data.fd;
            if(fd==STDIN_FILENO){
                fgets(buff,4096,stdin);
                //给addr1发送消息
                sendto(sockfd,buff,strlen(buff)+1,0,addr1,sizeof(struct sockaddr));
            }
            if(fd==sockfd){
                recvfrom(sockfd,buff,4096,0,NULL,NULL);
                printf("REC::%s\n",buff);
            }
        }
    }

    close(sockfd);
    return 0;
}

721作业:

01:在一对一聊天的基础上,使用select实现一对多的回显服务。(回显服务即接收到客户端发送的数据后,再回复给客户端)

一对一的喵:

//client.c
#include <func.h>
#define IP1 "192.168.235.128"
#define IP2 "42.194.149.92"
#define PORT1 8080
#define PORT2 13332

struct sockaddr* addr_create(const char* ip,int  port ){
    struct sockaddr_in* addr=(struct sockaddr_in*)malloc(sizeof(struct sockaddr_in));
    memset(addr,0,sizeof(*addr));
    addr->sin_family=AF_INET;
    addr->sin_port=htons(port);
    addr->sin_addr.s_addr=inet_addr(ip);
    return (struct sockaddr*)addr;
}

int main()
{
    int sofd=socket(AF_INET,SOCK_STREAM,0);
    if(sofd==-1){error(1,errno,"socket");}

    struct sockaddr* addr=addr_create(IP1,PORT1);
    int err=connect(sofd,addr,sizeof(*addr));
    if(err==-1){error(1,errno,"connect");}
    printf("connect sucess\n");

    fd_set set;
    FD_ZERO(&set);
    char buff[100]={0};

    while(1){
        FD_SET(STDIN_FILENO,&set);
        FD_SET(sofd,&set);
        select(sofd+1,&set,NULL,NULL,NULL);

        if(FD_ISSET(STDIN_FILENO,&set)){
            memset(buff,0,sizeof(buff));
            err=read(STDIN_FILENO,buff,sizeof(buff));
            if(strcmp(buff,"byby\n")==0){break;}
            send(sofd,buff,err-1,0);
        }
        if(FD_ISSET(sofd,&set)){
            memset(buff,0,sizeof(buff));
            err=recv(sofd,buff,sizeof(buff),0);
            if(err==0){printf("byebye\n");break;}
            printf("ret:  %d,recv:%s \n",err,buff);
        }
    }
    close(sofd);
    return 0;
}
//server.c
#include <func.h>
#define IP1 "192.168.235.128"
#define IP2 "42.194.149.92"
#define PORT1 8080
#define PORT2 13332

struct sockaddr* addr_create(const char* ip,int  port ){
    struct sockaddr_in* addr=(struct sockaddr_in*)malloc(sizeof(struct sockaddr_in));
    memset(addr,0,sizeof(*addr));
    addr->sin_family=AF_INET;
    addr->sin_port=htons(port);
    addr->sin_addr.s_addr=inet_addr(ip);
    return (struct sockaddr*)addr;
}

int main()
{
    int sofd=socket(AF_INET,SOCK_STREAM,0);
    if(sofd==-1){error(1,errno,"socket");}

    struct sockaddr* addr=addr_create(IP1,PORT1);
    int err=bind(sofd,addr,sizeof(*addr));
    if(err==-1){error(1,errno,"bimd");}
    printf("bind sucess\n");
    /* struct sockaddr_in*  addrin=(struct sockaddr_in*)addr; */
    /* printf("%s,%d\n",inet_ntoa(addr->sin_addr), */
    /*        sizeof((struct sockaddr_in*)addr.sin.port)); */
    err=listen(sofd,1);
    if(err==-1){error(1,errno,"listen");}

    struct sockaddr_in addr2;
    socklen_t len=sizeof(addr2);
    int peerfd=accept(sofd,(struct sockaddr*)&addr2,&len);
    printf("client :%s:%d has connect\n",inet_ntoa(addr2.sin_addr),
           ntohs(addr2.sin_port));
    // sofd--->peerfd

    fd_set set;
    FD_ZERO(&set);
    char buff[100]={0};

    while(1){
        FD_SET(STDIN_FILENO,&set);
        FD_SET(peerfd,&set);
        select(peerfd+1,&set,NULL,NULL,NULL);

        if(FD_ISSET(STDIN_FILENO,&set)){
            memset(buff,0,sizeof(buff));
            err=read(STDIN_FILENO,buff,sizeof(buff));
            if(strcmp(buff,"byby\n")==0){break;}
            send(peerfd,buff,err-1,0);
        }
        if(FD_ISSET(peerfd,&set)){
            memset(buff,0,sizeof(buff));
            err=recv(peerfd,buff,sizeof(buff),0);
            if(err==0){printf("byebye\n");break;}
            printf("ret:  %d,recv:%s \n",err,buff);
        }
    }
    close(sofd);
    return 0;
}
 一对多的服务器喵:
#include <func.h>
#define IP1 "192.168.235.128"
#define IP2 "42.194.149.92"
#define PORT1 8080
#define PORT2 13332

struct sockaddr* addr_create(const char* ip,int  port ){
    struct sockaddr_in* addr=(struct sockaddr_in*)malloc(sizeof(struct sockaddr_in));
    memset(addr,0,sizeof(*addr));
    addr->sin_family=AF_INET;
    addr->sin_port=htons(port);
    addr->sin_addr.s_addr=inet_addr(ip);
    return (struct sockaddr*)addr;
}

int main()
{
    int sofd=socket(AF_INET,SOCK_STREAM,0);
    if(sofd==-1){error(1,errno,"socket");}

    struct sockaddr* addr=addr_create(IP1,PORT1);
    int err=bind(sofd,addr,sizeof(*addr));
    if(err==-1){error(1,errno,"bimd");}
    printf("bind sucess\n");
    /* struct sockaddr_in*  addrin=(struct sockaddr_in*)addr; */
    /* printf("%s,%d\n",inet_ntoa(addr->sin_addr), */
    /*        sizeof((struct sockaddr_in*)addr.sin.port)); */
    err=listen(sofd,1);
    if(err==-1){error(1,errno,"listen");}

    struct sockaddr_in addr2;
    socklen_t len=sizeof(addr2);
    int peerfd=accept(sofd,(struct sockaddr*)&addr2,&len);
    printf("client :%s:%d has connect\n",inet_ntoa(addr2.sin_addr),
           ntohs(addr2.sin_port));
    // sofd--->peerfd

    fd_set set;
    FD_ZERO(&set);
    char buff[100]={0};

    while(1){
        FD_SET(STDIN_FILENO,&set);
        FD_SET(peerfd,&set);
        select(peerfd+1,&set,NULL,NULL,NULL);

        if(FD_ISSET(STDIN_FILENO,&set)){
            memset(buff,0,sizeof(buff));
            err=read(STDIN_FILENO,buff,sizeof(buff));
            if(strcmp(buff,"byby\n")==0){break;}
            send(peerfd,buff,err-1,0);
        }
        if(FD_ISSET(peerfd,&set)){
            memset(buff,0,sizeof(buff));
            err=recv(peerfd,buff,sizeof(buff),0);
            if(err==0){printf("byebye\n");break;}
            printf("ret:  %d,recv:%s \n",err,buff);
        }
    }
    close(sofd);
    return 0;
}

02:使用select编写聊天室程序:客户端和服务端使用tcp通信;服务端可以处理新客户端的连接和转发消息;客户端可以连入服务端并发送消息。

//server.c
#include <func.h>
#define IP1 "192.168.235.128"
#define IP2 "42.194.149.92"
#define PORT1 8080
#define PORT2 13332

//聊天室服务端
typedef struct conn_s{
    int netfd;
    int isalive;
}conn_t;

struct sockaddr* addr_create(const char* ip,int  port ){

    struct sockaddr_in* addr=(struct sockaddr_in*)malloc(sizeof(struct sockaddr_in));
    memset(addr,0,sizeof(*addr));
    addr->sin_family=AF_INET;
    addr->sin_port=htons(port);
    addr->sin_addr.s_addr=inet_addr(ip);
    return (struct sockaddr*)addr;
}


int main(int argc,char* argv[])
{
    struct sockaddr* addr=addr_create(IP1,PORT1);

    int sofd=socket(AF_INET,SOCK_STREAM,0);
    if(sofd==-1){error(1,errno,"socket");}

    bind(sofd,(struct sockaddr *)&addr,sizeof(addr));
    listen(sofd,10);
    
    //用于管理文件描述符集合,用于指示哪些文件描述符正在监听的 I/O 事件已经发生
    fd_set set;//select 监听的集合
    FD_ZERO(&set);
    FD_SET(sofd,&set);
    
    conn_t list[1024];
    memset(list,0,sizeof(list));
    int index;

    while(1){
        fd_set temp_set;//构建此次的监听合计
        memcpy(&temp_set,&set,sizeof(set));//cp ser temp_set

        select (10,&temp_set,NULL,NULL,NULL);

        if(FD_ISSET(sofd,&temp_set)){
            int netfd=accept(sofd,NULL,NULL);
            list[index].isalive=1;
            list[index].netfd=netfd;
            FD_SET(netfd,&set);//增加监听

            index++;
        }

        for(int i=0;i<index;i++){
            conn_t con=list[i];
            //isalive && isset==has new massege
            if(con.isalive==1&&FD_ISSET(con.netfd,&temp_set)){
                char buff[100]={0};
                int res_recv=recv(con.netfd,buff,sizeof(buff),0);
                if(res_recv==0){
                    //return 0   disconnect
                    list[i].isalive=0;
                    FD_CLR(con.netfd,&set);
                    close(list[i].netfd);
                }else{
                    //recv msg-->send  client
                    for(int j=0;j<index;j++){
                        if(list[j].isalive==0||j==i){
                            continue;
                            //跳过断开连接的客户端,跳过发信息过来的客户端
                        }
                        send(list[j].netfd,buff,sizeof(buff),0);
                    }
                }
            }
        }

    }
    printf("学姐我饿了\n");
    printf("我也是\n");

    close(sofd);
    free(addr);
    return 0;
}

722作业 :

01:使用epoll的流程是怎么样,每一步操作会涉及哪些数据结构?

02:select有哪些缺陷,epoll为什么比较高效?

03:epoll中的水平触发和边缘触发的区别是什么?使用边缘触发时,要注意什么呢?

04:采用TCP协议,通过epoll实现多客户端的回显服务,从而理解epoll的实现流程。
(epoll监听新连接的请求和回显已经建立好连接的消息)

05:使用epoll编写聊天室程序:客户端和服务端使用tcp通信;服务端可以处理新客户端的连接和转发消息;客户端可以连入服务端并发送消息。一个客户端10s未发送消息直接踢出

HTTP协议:

作业:

01:HTTP请求报文和响应报文由哪些部分组成?HTTP常用方法有哪些?HTTP常用状态码有哪些?

02:form-data的boundary起什么作用,有什么限制?

03:HTTP请求报文的报文体可以携带哪些类型的数据,分别是什么,各自有什么特点呢?

04:对称加密和非对称加密有什么区别?简要说明一下HTTPS的握手阶段流程。

05:C++代码实现:尝试实现一个静态网页服务端,返回给客户端一张图片 (提示:读取服务器本地的图片文件,再发送给客户端)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1953826.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

布尔盲注——多种方式实现及利用burpsuite爆破

目录 1、判断闭合符类型 2、爆数据库长度 3、查询库名 手动注入 burpsuite爆破 方法一&#xff1a;用ASCII码值转化爆破 方法二&#xff1a;left方法直接爆破字母 方法三&#xff1a;if方法爆破注入&#xff08;最简单&#xff09; 4、爆破表名 5、爆破具体值 当我们改变前端…

javaEE(1)

一. Web开发概述 Web开发:指的是从网页中向后端程序发送请求,与后端程序进行交互 Web服务器:是一种软件,向浏览器等Web客户端提供文档等数据,实现数据共享,它是一个容器,是一个连接用户和程序之间的中间键 二. Web开发环境搭建 我们要实现前后端交互,首先需要中间键Web服务…

pinia安装及简介

pinia简介 基本特点 轻量级&#xff1a;Pinia相比于传统的Vuex&#xff0c;体积更小&#xff0c;性能更好&#xff0c;只有大约1KB左右。 简化API&#xff1a;Pinia简化了状态管理库的使用方法&#xff0c;抛弃了Vuex中的mutations&#xff0c;只保留了state、getters和actions…

论文阅读:(DETR)End-to-End Object Detection with Transformers

论文阅读&#xff1a;&#xff08;DETR&#xff09;End-to-End Object Detection with Transformers 参考解读&#xff1a; 论文翻译&#xff1a;End-to-End Object Detection with Transformers&#xff08;DETR&#xff09;[已完结] - 怪盗kid的文章 - 知乎 指示函数&…

传输层(port)UDP/TCP——解决怎么发,发多少,出错了怎么办

**传输层&#xff1a;**负责数据能够从发送端传输接收端. 传输层所封装的报头里一定有&#xff1a;源端口号和目的端口号的。 **端口号&#xff1a;**可以标识一台主机中的唯一一个进程&#xff08;运用程序&#xff09;&#xff0c;这样当数据传输到传输层的时候就可以通过端…

电商项目之如何判断线程池是否执行完所有任务

文章目录 1 问题背景2 前言3 4种常用的方法4 代码4.1 isTerminated()4.2 线程池的任务总数是否等于已执行的任务数4.3 CountDownLatch计数器4.4 CyclicBarrier计数器 1 问题背景 真实生产环境的电商项目&#xff0c;常使用线程池应用于执行大批量操作达到高性能的效果。应用场景…

当全球银行系统“崩溃”时会发生什么?

有句名言&#xff1a;“当美国打喷嚏时&#xff0c;世界就会感冒……”换句话说&#xff0c;当人们对美国及其经济稳定性的信心下降时&#xff0c;其他经济体&#xff08;以及黄金、白银和股票等资产&#xff09;的价值往往会下降。 与任何其他资产类别一样&#xff0c;加密货…

Java并发编程深入浅出(个人造诣)

目录 串行&#xff0c;并行与并发&#xff1a; 并发编程的目的 如何保证多线程的安全&#xff08;并发编程思想&#xff09; 写后读思想&#xff1a;&#xff08;一个线程写后再让另一个线程读&#xff09; 如何保障写后读&#xff1f; 1、加锁&#xff1a;&#xff08;s…

Cocos Creator2D游戏开发(3)-飞机大战(1)-背景动起来

资源见: https://pan.baidu.com/s/1cryYNdBOry5A4YEEcLwhDQ?pwdzual 步骤 1, 让背景动起来 2, 玩家飞机显现,能操控,能发射子弹 3.敌机出现 4. 碰撞效果(子弹和敌机,敌机和玩家) 5. 积分和游戏结束 6. 游戏存档,对接微信小游戏,保存历史最高分 7. cocos发布到微信小游戏 资源…

【计算机网络】IP地址和子网掩码(IP地址篇)

个人主页&#xff1a;【&#x1f60a;个人主页】 系列专栏&#xff1a;【❤️计算机网络】 文章目录 前言IP地址网络地址网络地址的定义与组成作用分类网络地址的分配与管理 广播地址&#xff08;Broadcast Address&#xff09;定义构成类型作用注意事项 广播地址功能 组播地址…

【初阶数据结构篇】栈的实现(赋源码)

文章目录 栈1 代码位置2 概念与结构1.1概念1.2结构 2 栈的实现2.1 栈的初始化和销毁2.1.1 初始化2.1.2 销毁 2.2 栈顶插入和删除数据2.2.1 栈顶插入数据&#xff08;压栈&#xff09;2.2.2 栈顶删除数据&#xff08;出栈&#xff09; 2.3 返回栈顶数据2.4 返回栈的有效数据个数…

Jenkins持续部署

开发环境任务的代码只要有更新&#xff0c;Jenkins会自动获取新的代码并运行 1. pycharm和git本地集成 获取到下面的 Git可执行文件路径 2. pycharm和gitee远程仓库集成 先在pycharm中安装gitee插件 在设置中找到gitee&#xff0c;点击添加账户&#xff0c;并将自己的账户添…

(day26)leecode热题——找到字符串中所有字母异位词

描述 给定两个字符串 s 和 p&#xff0c;找到 s 中所有 p 的 异位词 的子串&#xff0c;返回这些子串的起始索引。不考虑答案输出的顺序。 异位词 指由相同字母重排列形成的字符串&#xff08;包括相同的字符串&#xff09;。 示例 1: 输入: s "cbaebabacd", p …

【QGroundControl二次开发】六. QGC地面站中视频流配置gstreamer

本文解决qgc源码编译后无法接收视频推流&#xff0c;原因是缺少gstreamer。 下面为windows安装流程&#xff0c;qgc版本为4.4.1稳定版 1. 安装gstreamer 官网链接&#xff1a;https://gstreamer.freedesktop.org/download/#windows 两个都要下载。安装的时候&#xff0c;在cu…

网络安全自学从入门到精通的制胜攻略!!!

在信息时代&#xff0c;网络安全已成为至关重要的领域。越来越多的人希望通过自学掌握这门技术&#xff0c;开启充满挑战与机遇的职业道路。以下是一份精心为您打造的网络安全自学攻略&#xff0c;助您在自学之旅中乘风破浪。 一、明确目标与兴趣方向 网络安全涵盖众多领域&am…

Java的四种引用类型

Java的四种引用类型 1. 强引用&#xff08;Strong Reference&#xff09;2. 软引用&#xff08;Soft Reference&#xff09;3. 弱引用&#xff08;Weak Reference&#xff09;4. 虚引用&#xff08;Phantom Reference&#xff09; &#x1f496;The Begin&#x1f496;点点关注…

硬件工程师笔面试真题汇总

目录 1、电阻 1&#xff09;上拉电阻的作用 2&#xff09;PTC热敏电阻作为电源电路保险丝的工作原理 2、电容 1&#xff09;电容的特性 2) 电容的特性曲线 3) 1uf的电容通常来滤除什么频率的信号 3、电感 4、二极管 1&#xff09;二极管特性 2&#xff09;二极管伏安…

MySQL练手 --- 1633. 各赛事的用户注册率

题目链接&#xff1a;1633. 各赛事的用户注册率 思路&#xff1a; 两张表&#xff0c;一张为Users用户表&#xff0c;该表存储着所有用户的 user_id 和 user_name 另一张表为Register注册表&#xff0c;该表存储着赛事id&#xff08;contest_id&#xff09;&#xff0c;和已…

NumpyPandas:Pandas库(25%-50%)

目录 前言 一、列操作 1.修改变量列 2.筛选变量列 3.删除变量列 4.添加变量列 二、数据类型的转换 1.查看数据类型 2.将 ok的int类型转换成float类型 3.将ar的float类型转换成int类型 三、建立索引 1.建立DataFrame时建立索引 2.在读入数据时建立索引 3.指定某列或…

PHP8.3.9安装记录,Phpmyadmin访问提示缺少mysqli

ubuntu 22.0.4 腾讯云主机 下载好依赖 sudo apt update sudo apt install -y build-essential libxml2-dev libssl-dev libcurl4-openssl-dev pkg-config libbz2-dev libreadline-dev libicu-dev libsqlite3-dev libwebp-dev 下载php8.3.9安装包 nullhttps://www.php.net/d…