0724,select +tcp 聊天室喵

目录

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 8081struct 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;//标准输入的文件描述符,通常为 0epoll_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 13332struct 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;//标准输入的文件描述符,通常为 0epoll_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 13332struct 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 13332struct 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--->peerfdfd_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 13332struct 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--->peerfdfd_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_setselect (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 massegeif(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   disconnectlist[i].isalive=0;FD_CLR(con.netfd,&set);close(list[i].netfd);}else{//recv msg-->send  clientfor(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.rhkb.cn/news/384205.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

懒人精灵安卓版纯本地离线文字识别插件

目的 懒人精灵是一款可以模拟鼠标和键盘操作的自动化工具。它可以帮助用户自动完成一些重复的、繁琐的任务&#xff0c;节省大量人工操作的时间。懒人精灵也包含图色功能&#xff0c;识别屏幕上的图像&#xff0c;根据图像的变化自动执行相应的操作。本篇文章主要讲解下更优秀的…

【屏显MCU】多媒体接口总结

本文主要介绍【屏显MCU】的基本概念&#xff0c;用于开发过程中的理解 以下是图层叠加示例 【屏显MCU】多媒体接口总结 0. 个人简介 && 授权须知1. 三大引擎1.1 【显示引擎】Display Engine1.1.1 【UI】 图层的概念1.1.2 【Video】 图层的概念1.1.3 图层的 Blending 的…

JAVA笔记十七

十七、File-IO流 1.I/O的概念和java.io包 (1)输入&#xff1a;外部源—>程序 输出&#xff1a;程序—>输出目标 外部源、输出目标&#xff1a;磁盘文件、网络连接、内存缓存等 (2)java程序通过流执行I/O 流是一种抽象&#xff0c;可以用来产生信息或者使用信息&#…

jenkins自动化持续集成

一、持续集成优势 1.1 解放重复劳动 一次设置&#xff0c;多次复用。持续集成任务可以解放集成、测试、部署等重复性劳动&#xff0c;通过自动化任务能够显著提升集成频率。 1.2 更快解决问题 接入持续集成任务后&#xff0c;能够更早地感知变更后效果&#xff0c;及时进入…

【OpenCV C++20 学习笔记】基本图像容器——Mat

【OpenCV C20 学习笔记】基本图像容器——Mat 概述Mat内部结构引用计数机制颜色数据格式 显式创建Mat对象使用cv::Mat::Mat构造函数矩阵的数据项 使用数组进行初始化的构造函数cv::Mat::create函数MATLAB风格的初始化小型矩阵通过复制创建Mat对象 Mat对象的输出其他普通数据项的…

在图神经网络(GNN)上进行关系推理的新架构

开发能够学习推理的模型是一个众所周知的具有挑战性的问题&#xff0c;在这个领域中&#xff0c;使用图神经网络&#xff08;GNNs&#xff09;似乎是一个自然的选择。然而&#xff0c;以往关于使用GNNs进行推理的工作表明&#xff0c;当这些模型面对需要比训练时更长推理链的测…

某数据泄露防护(DLP)系统NoticeAjax接口SQL注入漏洞复现 [附POC]

文章目录 某数据泄露防护(DLP)系统NoticeAjax接口SQL注入漏洞复现 [附POC]0x01 前言0x02 漏洞描述0x03 影响版本0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现某数据泄露防护(DLP)系统NoticeAjax接口SQL注入漏洞复现 [附POC] 0x01 前言 免责声明:请勿利用文章内…

SpringBoot 项目配置文件注释乱码的问题解决方案

一、问题描述 在项目的配置文件中&#xff0c;我们写了一些注释&#xff0c;如下所示&#xff1a; 但是再次打开注释会变成乱码&#xff0c;如下所示&#xff1a; 那么如何解决呢&#xff1f; 二、解决方案 1. 点击” File→Setting" 2. 搜索“File Encodings”, 将框…

DDoS 究竟在攻击什么?

分布式拒绝服务&#xff08;DDoS&#xff09;攻击是一种常见的网络攻击形式&#xff0c;攻击者通过向目标服务端发送大量的请求&#xff0c;使目标服务端无法进行网络连接&#xff0c;无法正常提供服务。 DDoS 攻击通常是由大量的分布在全球各地的 “僵尸” 计算机&#xff08…

力扣高频SQL 50题(基础版)第七题

文章目录 力扣高频SQL 50题&#xff08;基础版&#xff09;第七题1068. 产品销售分析 I题目说明思路分析实现过程准备数据&#xff1a;实现方式&#xff1a;结果截图:总结&#xff1a; 力扣高频SQL 50题&#xff08;基础版&#xff09;第七题 1068. 产品销售分析 I 题目说明 …

Android adb shell ps进程查找以及kill

Android adb shell ps进程查找以及kill 列出当前Android手机上运行的所有进程信息如PID等&#xff1a; adb shell ps 但是这样会列出一大堆进程信息&#xff0c;不便于定向查阅&#xff0c;可以使用关键词查找&#xff1a; adb shell "ps | grep 关键词" 关键词查…

Mysql中如何实现两列的值互换?给你提供些思路。

文章目录 Mysql中如何实现两列的值互换1、第一感觉此sql应该能处理问题了2、需要一个地方存要替换的值&#xff0c;不然两列搞不定。2.1 加第三列&#xff1f;&#xff08;能解决&#xff0c;但是看起来呆呆&#xff09;2.2 上临时表&#xff08;搞点弯路走走&#xff09; 示例…

Linux学习第55天:Linux 4G 通信实验(更快、更高、更强)

Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 无论是有线网络还是WiFi都是摆脱不了布线的尴尬&#xff0c;而4G通信可以彻底拜托网线的束缚&#xff0c;实现无线网络通信。 而说到4G就不得不提到5G&#xff0c;中…

jenkins删除历史构建记录

1、 登录jenkins&#xff0c;进入【Manage Jenkins】-【Script Console】&#xff0c;输入&#xff1a; def jobName "Test" //删除的项目名称 def maxNumber 60 // 保留的最小编号&#xff0c;意味着小于该编号的构建都将被删除 Jenkins.instance.getItemByFullN…

单元测试--Junit

Junit是Java的单元测试框架提供了一些注解方便我们进行单元测试 1. 常用注解 常用注解&#xff1a; TestBeforeAll&#xff0c;AfterAllBeforeEach&#xff0c;AfterEach 使用这些注解需要先引入依赖&#xff1a; <dependency><groupId>org.junit.jupiter<…

Vue3与Element-plus配合 直接修改表格中的一项数据——控制输入框的显示与隐藏

利用控制与隐藏输入框,直接修改表格中的每一项数据。 <!-- 表格模块 --> <div><el-table :data"tablelist" style"width: 100%"><el-table-column align"center" prop"deposit" label"接单押金">&l…

【 C++ 】 一文搞定——引用、内联、命名空间、缺省、重载

前言&#xff1a;这篇文章将带您了解C基础中的知识点——命名空间、引用、内联、缺省、重载 &#x1f618;我的主页&#xff1a;OMGmyhair-CSDN博客 一、命名空间namespace 1.可以嵌套定义&#xff0c;但是只能定义在全局 namespace ly {int student 1;int age 21;void Pr…

windows wsl ubuntu系统安装桌面可视化

参考&#xff1a; https://www.bilibili.com/read/cv33557374/ 1&#xff09;首先先安装好wsl ubuntu系统 2&#xff09;安装 Ubuntu 桌面版 sudo apt purge -y acpid acpi-support modemmanagersudo apt-mark hold acpid acpi-support modemmanager sudo apt install ubunt…

数据库连接断开后,DBAPI的数据源如何自动重连

现象 在使用DBAPI的过程中&#xff0c;如果网络抖动导致数据库连接不上&#xff0c;发现DBAPI的数据源不能重连&#xff0c;必须重启DBAPI才能连上数据库 解决办法 在数据源的连接池参数配置druid.breakAfterAcquireFailurefalse注意在企业版的4.1.1及以上版本才可以配置连接…

捉虫笔记(1)之 WinDbg符号配置

WinDbg符号配置 1、WinDbg简单介绍 WinDbg 是微软的一款强大的调试工具&#xff0c;用于 Windows 平台的内核和用户模式调试。它提供了一系列强大的功能&#xff0c;包括内存和寄存器的查看、断点设置、堆栈跟踪、性能分析等。 WinDbg 的历史可以追溯到微软早期的调试工具&a…