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.mzph.cn/diannao/51017.shtml

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

相关文章

Pyppeteer 的使用

puppeteer 是基于Node.js 开发的一个工具, 有了它&#xff0c;我们可以利用 JavaScript 控制 Chrome 浏览器的一些操作。当然&#xff0c; puppeteer 也可以用于网络爬虫&#xff0c;其 API 及其完善&#xff0c;功能非常强大。 Pyppeteer 其实是 puppeteer 的 python 实现&…

.net 连接达梦数据库开发环境部署

.net 开发环境部署 1. 环境准备 测试工具 Visual Studio2022 数据库版本 dm8 2. 搭建过程 1 &#xff09;创建新项目 2 &#xff09;选择创建空项目 3 &#xff09;配置新项目 4 &#xff09;右键 DM1 新建一个项 5 &#xff09;加 载 驱 动 &#xff0c; 新 建 …

0722_驱动3 地址映射驱动点灯

一、为什么需要地址映射 在芯片手册上查看到的地址属于物理地址&#xff0c;在硬件层 在内核空间地址属于虚拟地址&#xff0c;在内核层 在驱动中&#xff0c;操作的是虚拟地址 需要将物理地址《--mmu内存管理单元--》虚拟地址映射 二、映射API接口 void *ioremap(unsigned lon…

backtrace

介绍 arm平台的调用栈与x86平台的调用栈大致相同&#xff0c;稍微有些区别&#xff0c;主要在于栈帧的压栈内容和传参方式不同。在arm平台的不同程序&#xff0c;采用的编译选项不同&#xff0c;程序运行期间的栈帧也会不同。有些工具在对arm的调用栈回溯时&#xff0c;可能会…

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

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

Dify中语音和文字间转换问题的一种暂时注释方式

本文主要解释了Dify中语音和文字间转换可能会遇到的问题&#xff0c;并给出了一种暂时注释的解决方案。 一.文本转语音可能问题 本地部署文本转语音时&#xff0c;如果遇到如下问题&#xff0c;安装ffmpeg即可。但是如果安装后&#xff0c;重启系统还是遇到这个问题该如何办&…

分库分表——从理论到最佳实践

目录 1、为什么要分库分表&#xff1f;2、切分方案有哪些&#xff1f;2.1 分库2.1.1 垂直分库2.1.2 水平分库 2.2 分表2.2.1 垂直分表2.2.2 水平分表 2.3 分库分表 3、数据水平分片方法3.1 Hash分片3.2 一致性Hash分片3.3 Range分片 4、分库分表的挑战4.1 分布式id4.2 分布式事…

LLM:归一化 总结

一、Batch Normalization 原理 Batch Normalization 是一种用于加速神经网络训练并提高稳定性的技术。它通过在每一层网络的激活值上进行归一化处理&#xff0c;使得每一层的输入分布更加稳定&#xff0c;从而加速训练过程&#xff0c;并且减轻了对参数初始化的依赖。 公式 …

分类模型——逻辑回归和Fisher线性判别分析

个人学习笔记&#xff0c;课程为数学建模清风付费课程 目录 一、引例 二、逻辑回归 2.1线性概率模型 2.2Fisher线性判别分析 2.3两点分布&#xff08;伯努利分布&#xff09; 2.4连接函数的取法 2.5如何求解 2.6如何用于分类 三、SPSS 3.1二元分类 3.1.1逻辑回…

MySQL内如何改变编码格式

查找数据库的编码格式&#xff1a; show variables like character%;具体内容时这些 在创建表时设定编码格式&#xff1a; create database <要创建的数据库的名字> charset utf8; 修改数据库默认编码&#xff1a; set character_set_databaseutf8mb4; character_…

eclipse ui bug

eclipse ui bug界面缺陷&#xff0c;可能项目过多&#xff0c;特别maven项目过多&#xff0c;下载&#xff0c;自动编译&#xff0c;加载更新界面异常 所有窗口死活Restore不回去了 1&#xff09;尝试创建项目&#xff0c;还原界面&#xff0c;失败 2&#xff09;关闭所有窗口&…

将TP5链接导入笔影个人博客代码

首先第一步&#xff0c;打开界面 第二步&#xff0c;这里卡住了&#xff0c;无法看到源代码&#xff0c;我们使用其他软件看看源代码 调试乱码&#xff0c;因为没有找到相应的笔影个人博客源码。源码在桌面上。询问百度&#xff0c;说了有的没的一大堆。 尝试的结果就是失败…

时间复杂度与O(n)

文章目录 1 复杂度分析1.1 时间复杂度1.1.1 循环执行次数1.1.2 大O(n)表示法 1.2 空间复杂度 1 复杂度分析 1.1 时间复杂度 ​ 时间复杂度用来表示算法运行时间的长短&#xff0c;用来定性的描述程序的运行时间。要了解时间复杂度&#xff0c;我们需要先了解程序执行的次数。…

机器学习(二十二):精度和召回率

一、倾斜数据集 倾斜数据集&#xff1a;一个数据集中的正面和负面例子的比例非常不平衡&#xff0c;比如数据集中&#xff0c;结果为1的占比20%&#xff0c;结果为0的占比80% 例子&#xff1a;如果数据集的结果中只有0.5%是1&#xff0c;其余结果是0。有一个模型的预测准确度…

【信创】udisk2服务异常导致U盘使用中自动移除问题解决

原文链接&#xff1a;【信创】udisk2服务异常导致U盘使用中自动移除问题解决 Hello&#xff0c;大家好啊&#xff01;今天给大家带来一篇关于在信创终端操作系统上由于udisk2服务异常导致U盘等移动设备在使用中自动移除问题的排查文章。udisk2是一个管理存储设备的服务&#xf…

【计算机网络】OSPF单区域实验

一&#xff1a;实验目的 1&#xff1a;掌握在路由器上配置OSPF单区域。 2&#xff1a;学习OSPF协议的原理&#xff0c;及其网络拓扑结构改变后的变化。 二&#xff1a;实验仪器设备及软件 硬件&#xff1a;RCMS交换机、网线、内网网卡接口、Windows 2019操作系统的计算机等。…

Vue 3 实现左侧列表点击跳转滚动到右侧对应区域的功能

使用 Vue 3 实现左侧列表点击跳转到右侧对应区域的功能 1. 引言 在这篇博客中&#xff0c;我们将展示如何使用 Vue 3 实现一个简单的页面布局&#xff0c;其中左侧是一个列表&#xff0c;点击列表项时&#xff0c;右侧会平滑滚动到对应的内容区域。这种布局在很多应用场景中都…

Llama 3.1 405B 详解

2024 年 7 月 23 日星期二&#xff0c;Meta 宣布推出 Llama 3.1&#xff0c;这是其Llama 系列大型语言模型 (LLM)的最新版本。虽然只是对 Llama 3 模型进行小幅更新&#xff0c;但它特别引入了Llama 3.1 405B——一个 4050 亿参数的模型&#xff0c;这是迄今为止世界上最大的开…

运行ruoyi

nacos 数据库配置 修改nacos/conf/application.properties 单机版运行 startup.cmd -m standalone redis 运行后端 运行gateway,auth,modules/system模块 可能遇到的问题&#xff1a;端口正在使用 解决 netstat -ano | findstr 9200 taskkill -pid 18284 -f

JAVA同城圈子达人交友系统源码支持微信小程序+公众号+H5+APP

&#x1f308; 同城圈子达人交友系统&#xff0c;遇见志同道合的TA&#xff01; &#x1f389; 开篇&#xff1a;告别孤单&#xff0c;同城圈子等你来探索&#xff01; 在这个快节奏的城市生活中&#xff0c;你是否常常感到孤独&#xff0c;渴望找到一群志同道合的朋友&#…