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

帮别人做违法网站会判刑吗三亚做网站公司

帮别人做违法网站会判刑吗,三亚做网站公司,举报网站建设情况汇报,制作相册的软件app免费刷题 服务器多客户端连接核心要点 多进程服务器 实现原理 fork子进程:每次accept新客户端后,调用fork创建子进程。独立处理:子进程负责与客户端通信(如read/write),父进程继续监听新连接。 特点 隔离性…

刷题

服务器多客户端连接核心要点


多进程服务器

实现原理

  • fork子进程:每次accept新客户端后,调用fork创建子进程。
  • 独立处理:子进程负责与客户端通信(如read/write),父进程继续监听新连接。

特点

  • 隔离性高:进程间资源独立,避免数据竞争。
  • 资源消耗大:频繁创建进程导致内存和CPU开销高。

多线程服务器

实现原理

  • 创建新线程accept后生成线程处理客户端请求。
  • 线程函数:在线程内执行read/write操作。

特点

  • 轻量级:线程共享进程资源,开销低于进程。
  • 需同步机制:需使用互斥锁(mutex)或信号量避免数据竞争。

多路I/O模型

核心问题

  • 阻塞冲突:传统acceptread相互阻塞,无法同时处理多客户端。
  • 解决方案:通过非阻塞模型(select/poll)统一监听所有描述符。

Select模型

流程
  1. 初始化监视列表
fd_set read_fds;
FD_ZERO(&read_fds);          // 清空列表
FD_SET(server_fd, &read_fds); // 添加服务端套接字
  1. 循环监听
    select(max_fd + 1, &read_fds, NULL, NULL, NULL); // 阻塞直至描述符激活
  2. 处理激活描述符
    • 遍历描述符,通过FD_ISSET判断是否激活。
    • 服务端套接字激活:调用accept接受新客户端。
    • 客户端套接字激活:调用read读取数据。
缺点
  • 效率低:每次调用需遍历所有描述符。
  • 监视列表上限:默认限制1024个描述符。

Poll模型

流程
  1. 初始化监视列表
struct pollfd fds[MAX_CLIENTS];
fds[0].fd = server_fd;
fds[0].events = POLLIN; // 监视可读事件
  1. 循环监听
    poll(fds, nfds, -1); // 永久阻塞直至事件触发
  2. 处理激活描述符
    • 遍历fds数组,检查revents是否为POLLIN
    • 服务端激活:accept新客户端并加入列表。
    • 客户端激活:read数据并响应。
优点
  • 无描述符数量限制:支持动态扩展。
  • 事件类型灵活:可同时监视读写和异常事件。

模型对比

特性SelectPoll
描述符上限1024(系统默认)无限制
效率O(n)遍历O(n)遍历
事件类型仅可读/可写/异常支持自定义事件(如POLLIN)
跨平台支持广泛支持Linux专用

实际应用场景

  • 作业要求
    • 服务器端:使用poll模型处理多客户端。
    • 客户端1select模型实现非阻塞通信。
    • 客户端2:多线程处理输入/输出。
  • 典型场景
    • 实时聊天系统:服务器通过poll管理多个客户端会话。
    • 高并发服务器select/poll适用于低并发场景,epoll适合高并发。
  • pollk.c
    #include "head.h"#define MAX_CLIENTS 10 // 最多10个客户端// 将一个拥有{描述符,监视方式,激活形式}的结构体变量fd,存入监视列表arr中,并且监视列表的长度len自增
    void insert_fd(struct pollfd arr[], struct pollfd newfd, int* len) {arr[*len] = newfd; // 将新的pollfd结构体存入数组指定位置(*len)++; // 监视列表长度加1
    }// 将要移除的描述符fd,从监视列表arr中删除,并且监视列表长度len自减1
    void remove_fd(struct pollfd* arr, int fd, int* len) {for (int i = 0; i < *len; i++) {if (arr[i].fd == fd) { // 查找要移除的描述符在数组中的位置for (int j = i; j < *len - 1; j++) {arr[j] = arr[j + 1]; // 后面的元素向前移动,覆盖要移除的元素}break;}}(*len)--; // 监视列表长度减1
    }int main(int argc, const char *argv[]) {if (argc < 2) { // 检查命令行参数,确保输入了端口号printf("请输入端口号\n");return 1;}short port = atoi(argv[1]); // 将命令行输入的端口号字符串转换为short类型// 创建TCP类型的服务器套接字int server = socket(AF_INET, SOCK_STREAM, 0);struct sockaddr_in addr = {0};addr.sin_family = AF_INET; // 设置地址族为IPv4addr.sin_port = htons(port); // 将端口号转换为网络字节序addr.sin_addr.s_addr = inet_addr("0.0.0.0"); // 监听所有可用的本地IP地址// 将套接字绑定到指定的地址和端口if (bind(server, (struct sockaddr*)&addr, sizeof(addr)) == -1) {perror("bind");                                                                                                          return 1;}listen(server, MAX_CLIENTS); // 开始监听,设置最大等待连接数struct pollfd list[MAX_CLIENTS + 1] = {0}; // 定义pollfd结构体数组,用于存储要监视的描述符及其相关信息int list_len = 0; // 记录监视列表中描述符的数量// 准备要监视的服务器描述符(关注读事件)struct pollfd poll_server = {.fd = server,.events = POLLIN,.revents = 0};insert_fd(list, poll_server, &list_len); // 将服务器描述符加入监视列表printf("服务器启动,监听端口 %d...\n", port);while (1) {// 调用poll函数,阻塞等待监视列表中的描述符有事件发生poll(list, list_len, -1);for (int i = 0; i < list_len; i++) {int fd = list[i].fd;// 检查描述符的revents是否有读事件(POLLIN)发生if (list[i].revents & POLLIN) {if (fd == server) { // 服务器描述符有读事件,说明有新客户端连接struct sockaddr_in client_addr;socklen_t client_addr_len = sizeof(client_addr);int client = accept(server, (struct sockaddr *)&client_addr, &client_addr_len);if (client == -1) {perror("accept");continue;}printf("新客户端连接: %d\n", client);// 准备要监视的新客户端描述符(关注读事件)struct pollfd poll_client = {.fd = client,.events = POLLIN,.revents = 0};insert_fd(list, poll_client, &list_len); // 将新客户端描述符加入监视列表} else { // 客户端描述符有读事件,说明客户端发送了数据char buf[1024] = {0};int res = read(fd, buf, sizeof(buf));if (res <= 0) { // 处理客户端断开if (res == 0) {printf("客户端 %d 断开连接\n", fd);} else {perror("read");}close(fd);remove_fd(list, fd, &list_len); // 从监视列表中移除客户端描述符} else { // 转发数据给其他客户端for (int j = 0; j < list_len; j++) {if (list[j].fd != fd && list[j].fd != server) {write(list[j].fd, buf, res);}}}}}}}return 0;
    }

    selectk.c

    #include "head.h"int main(int argc, const char *argv[]) {if (argc < 2) {printf("请输入端口号\n");return 1;}int port = atoi(argv[1]);int client_fd = socket(AF_INET, SOCK_STREAM, 0);struct sockaddr_in addr = {0};addr.sin_family = AF_INET;addr.sin_port = htons(port);addr.sin_addr.s_addr = INADDR_ANY;if (connect(client_fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {perror("connect");return 1;}fd_set rset;int max_fd = client_fd;while (1) {FD_ZERO(&rset);FD_SET(client_fd, &rset);FD_SET(0, &rset); // 监控标准输入int ret = select(max_fd + 1, &rset, NULL, NULL, NULL);if (ret == -1) {perror("select");continue;}if (FD_ISSET(0, &rset)) { // 处理键盘输入char buf[1024] = {0};fgets(buf, sizeof(buf), stdin);buf[strcspn(buf, "\n")] = 0; // 去除换行符                                write(client_fd, buf, strlen(buf));}if (FD_ISSET(client_fd, &rset)) { // 处理接收消息char buf[1024] = {0};int res = read(client_fd, buf, sizeof(buf));if (res <= 0) {if (res == 0) {printf("服务器断开连接\n");} else {perror("read");}close(client_fd);return 1;}printf("收到消息: %s\n", buf);}}close(client_fd);return 0;
    }

    xiank.c

    #include "head.h"void *send_msg(void *arg) {int client_fd = *(int *)arg;while (1) {char buf[1024] = {0};fgets(buf, sizeof(buf), stdin);buf[strcspn(buf, "\n")] = 0; // 去除换行符write(client_fd, buf, strlen(buf));}
    }void *recv_msg(void *arg) {int client_fd = *(int *)arg;while (1) {char buf[1024] = {0};int res = read(client_fd, buf, sizeof(buf));if (res <= 0) { // 处理服务器断开if (res == 0) {printf("服务器断开连接\n");} else {perror("read");}close(client_fd);pthread_exit(NULL);}printf("收到消息: %s\n", buf);}
    }int main(int argc, const char *argv[]) {if (argc < 2) {printf("请输入端口号\n");return 1;}int port = atoi(argv[1]);int client_fd = socket(AF_INET, SOCK_STREAM, 0);struct sockaddr_in addr = {0};addr.sin_family = AF_INET;addr.sin_port = htons(port);addr.sin_addr.s_addr = INADDR_ANY;if (connect(client_fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {perror("connect");return 1;}pthread_t send_tid, recv_tid;pthread_create(&send_tid, NULL, send_msg, &client_fd); // 启动发送线程pthread_create(&recv_tid, NULL, recv_msg, &client_fd); // 启动接收线程pthread_join(send_tid, NULL);pthread_join(recv_tid, NULL);close(client_fd);return 0;
    }

总结:多进程/线程适合简单场景,多路I/O模型(select/poll)通过非阻塞监听提升效率,需根据并发需求选择模型。

http://www.dtcms.com/wzjs/597299.html

相关文章:

  • 信丰县建设局网站网站与系统对接图文方案
  • 网站开发工具可视化昆明网站的优化
  • 聊城营销网站建设价格东莞三网合一网站制作
  • 网站开发怎么让别人看到做p2p网站费用
  • jsp网站建设模板烟台网站制作公司在线咨询
  • 新学校网站建设成果房产网站cms
  • 奉化建设局网站广州最新通告
  • 重庆市网上房地产官网电脑优化大师有用吗
  • 支付单页网站模板商业设计说明
  • 呼和浩特电子商务网站建设站内优化包括哪些
  • 做盗版视频网站成本多少电子商务的发展现状和前景趋势
  • 做包装找灵感看什么网站友情链接中有个网站域名过期了会影响
  • 自助建设视频网站codepen wordpress
  • 局门户网站的建设方案宣传册样式
  • 有免费做理化试验的网站吗hao123网站难做吗
  • 制作公司网站用阿里云本人找做钢筋笼的活网站
  • 网站服务器租用价格多少钱一年wordpress架站教程
  • 济源做网站的好公司施工企业qc小组
  • 网站开发需求文档prd模板WordPress快速发布文章
  • wordpress站长之家贵阳58同城做网站公司
  • 网站微商城的建设运营实践和思考网站增加流量
  • 虚拟网站怎么做的搭建电商平台网站
  • 武夷山网站设计网站广告收费标准
  • 最早的做团购的网站网站开发模板系统
  • 青海网站 建设网页传奇国度
  • 东莞凤岗网站制作蜘蛛网站长工作职责
  • 有哪些做壁纸的网站好网站建设整个流程
  • .jsp网站开发技术wordpress 房产插件
  • 湖南做网站的公司排名最新网站建设软件
  • 如何申请域名做网站郑州电力高等专科学校