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

开封景区网站建设项目方案烟台高端品牌网站建设

开封景区网站建设项目方案,烟台高端品牌网站建设,网站做推广需要多少钱,网页设计html代码成品图片目录 第一章:select基础 1.1 select概述 1.2 select的使用场景 1.3 select的函数原型 1.4 fd_set和timeval结构体 1.5 select的基本流程 1.6 select的局限性 1.7 小结 第二章:select的高级使用 2.1 处理select的超时 2.1.1 设置永久等待 2.1.…

目录

 

第一章:select基础

1.1 select概述

1.2 select的使用场景

1.3 select的函数原型

1.4 fd_set和timeval结构体

1.5 select的基本流程

1.6 select的局限性

1.7 小结

第二章:select的高级使用

2.1 处理select的超时

2.1.1 设置永久等待

2.1.2 设置非阻塞等待

2.2 避免select的局限性

2.2.1 使用poll代替select

2.2.2 使用epoll(仅限于Linux)

2.3 select的错误处理

2.4 select在多线程环境中的应用

2.5 小结

第三章:select的应用实例

3.1 简单的echo服务器

3.1.1 echo服务器的实现

3.2 并发聊天服务器

3.3 小结


 

第一章:select基础

1.1 select概述

select是C语言中用于IO多路复用的一个系统调用,它允许程序监视多个文件描述符(通常是网络套接字)的状态,以便在某个文件描述符准备好进行IO操作时获得通知。select的这种能力使得单个线程能够管理多个并发连接,从而实现高效的并发处理。

1.2 select的使用场景

select通常用于以下场景:

  • 当需要同时处理多个套接字时,例如在网络服务器中。
  • 当需要同时监听标准输入和其他套接字时。
  • 当需要等待多个套接字事件(如读就绪、写就绪、异常)时。

1.3 select的函数原型

select的函数原型如下:

#include <sys/select.h>int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);
  • nfds:监视的文件描述符集合中最大文件描述符加1。
  • readfds:指向fd_set结构的指针,用于监视读就绪的文件描述符。
  • writefds:指向fd_set结构的指针,用于监视写就绪的文件描述符。
  • exceptfds:指向fd_set结构的指针,用于监视异常的文件描述符。
  • timeout:指向timeval结构的指针,用于设置select的超时时间。

1.4 fd_set和timeval结构体

fd_set是一个位掩码,用于表示文件描述符集合。在select中,它用来指定需要监视的文件描述符。timeval结构体用于指定select函数的超时时间。

struct timeval {long tv_sec;  // 秒long tv_usec; // 微秒
};

1.5 select的基本流程

使用select的基本流程如下:

  1. 初始化fd_set集合,将需要监视的文件描述符加入到相应的集合中。
  2. 调用select函数,等待文件描述符就绪或超时。
  3. 检查select返回值,处理就绪的文件描述符。
  4. 根据需要重复以上步骤。

1.6 select的局限性

select虽然是一个强大的工具,但它也有局限性:

  • fd_set集合的大小受限于系统定义的FD_SETSIZE,通常为1024,这意味着select不能有效地处理超过1024个并发连接。
  • 每次调用select都需要重新设置文件描述符集合,这在有大量文件描述符时效率较低。
  • select返回后,需要遍历整个文件描述符集合来确定哪些文件描述符就绪,这在高并发场景下可能成为性能瓶颈。

1.7 小结

本章介绍了select的基础知识,包括select的使用场景、函数原型、基本流程以及局限性。通过本章的学习,读者应该对select有了初步的了解,为后续深入学习select的高级使用和应用实例打下了基础。在下一章中,我们将探讨select的高级使用技巧,包括如何处理select的超时、如何避免select的局限性等。


第二章:select的高级使用

2.1 处理select的超时

在select中,超时参数timeout可以用来指定select函数等待的最大时间。如果在这个时间内没有任何文件描述符就绪,select将返回0。正确处理select的超时对于实现高效的网络程序至关重要。

2.1.1 设置永久等待

如果要使select永久等待,直到至少一个文件描述符就绪,可以将timeout设置为NULL:

struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 0;int ret = select(nfds, &readfds, &writefds, &exceptfds, NULL);

2.1.2 设置非阻塞等待

如果要使select在指定的时间后超时,可以设置timeout结构体的tv_sectv_usec字段:

struct timeval timeout;
timeout.tv_sec = 5;  // 等待5秒
timeout.tv_usec = 0; // 微秒int ret = select(nfds, &readfds, &writefds, &exceptfds, &timeout);

2.2 避免select的局限性

虽然select有局限性,但可以通过一些技巧来避免或减轻这些问题。

2.2.1 使用poll代替select

poll是另一个IO多路复用函数,它没有select的文件描述符数量限制,并且提供了更高效的接口来处理大量的文件描述符。

2.2.2 使用epoll(仅限于Linux)

epoll是Linux特有的IO多路复用机制,它解决了select和poll的一些问题,如文件描述符数量限制和效率问题。epoll使用事件驱动的机制,可以高效地处理大量的文件描述符。

2.3 select的错误处理

select在调用过程中可能会遇到错误,常见的错误包括:

  • EBADF:文件描述符集合中有无效的文件描述符。
  • EINTR:select被信号中断。
  • EINVAL:select的参数无效,如nfds小于0或timeout的值非法。

正确处理这些错误对于确保程序的健壮性非常重要。

2.4 select在多线程环境中的应用

在多线程环境中,select可以与线程结合起来使用,以提高程序的性能和并发处理能力。例如,可以在一个线程中使用select来监听多个套接字,然后在其他线程中处理就绪的套接字。

2.5 小结

本章介绍了select的高级使用,包括处理select的超时、避免select的局限性、错误处理以及在多线程环境中的应用。通过本章的学习,读者应该能够更加熟练地使用select,并能够应对一些复杂的网络编程场景。在下一章中,我们将通过一些实际的应用实例来进一步巩固对select的理解。


第三章:select的应用实例

3.1 简单的echo服务器

echo服务器是一个基本的网络编程实例,它接收客户端发送的数据并将其原样返回。使用select可以轻松实现一个多客户端的echo服务器。

3.1.1 echo服务器的实现

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>#define MAX_CLIENTS 10
#define BUFFER_SIZE 1024int main() {int server_fd, client_fd, max_fd;struct sockaddr_in server_addr, client_addr;socklen_t client_addr_len;fd_set readfds, temp_readfds;char buffer[BUFFER_SIZE];int client_sockets[MAX_CLIENTS] = {0};// 创建套接字server_fd = socket(AF_INET, SOCK_STREAM, 0);if (server_fd < 0) {perror("socket creation failed");exit(EXIT_FAILURE);}// 绑定地址和端口memset(&server_addr, 0, sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_addr.s_addr = INADDR_ANY;server_addr.sin_port = htons(12345);if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {perror("bind failed");exit(EXIT_FAILURE);}// 监听if (listen(server_fd, MAX_CLIENTS) < 0) {perror("listen failed");exit(EXIT_FAILURE);}// 初始化fd_setFD_ZERO(&readfds);FD_SET(server_fd, &readfds);max_fd = server_fd;while (1) {temp_readfds = readfds;// select等待就绪文件描述符int activity = select(max_fd + 1, &temp_readfds, NULL, NULL, NULL);if (activity < 0) {perror("select failed");exit(EXIT_FAILURE);}// 检查服务器套接字if (FD_ISSET(server_fd, &temp_readfds)) {client_addr_len = sizeof(client_addr);client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_addr_len);if (client_fd < 0) {perror("accept failed");exit(EXIT_FAILURE);}printf("New client connected, socket fd is %d\n", client_fd);// 添加到客户端套接字数组for (int i = 0; i < MAX_CLIENTS; i++) {if (client_sockets[i] == 0) {client_sockets[i] = client_fd;break;}}// 更新最大文件描述符if (client_fd > max_fd) {max_fd = client_fd;}}// 检查客户端套接字for (int i = 0; i < MAX_CLIENTS; i++) {client_fd = client_sockets[i];if (client_fd > 0 && FD_ISSET(client_fd, &temp_readfds)) {memset(buffer, 0, BUFFER_SIZE);int bytes_received = recv(client_fd, buffer, BUFFER_SIZE, 0);if (bytes_received <= 0) {// 客户端断开连接close(client_fd);client_sockets[i] = 0;} else {// 发送回显数据send(client_fd, buffer, bytes_received, 0);}}}}return 0;
}

3.2 并发聊天服务器

聊天服务器是一个稍微复杂的应用实例,它允许多个客户端连接并相互发送消息。使用select可以同时处理多个客户端的连接和消息传递。

3.2.1 聊天服务器的实现

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <pthread.h>#define MAX_CLIENTS 10
#define BUFFER_SIZE 1024typedef struct {int client_fd;struct sockaddr_in client_addr;
} client_info;client_info clients[MAX_CLIENTS];
int num_clients = 0;
pthread_mutex_t lock;void *client_handler(void *arg) {client_info *client = (client_info *)arg;char buffer[BUFFER_SIZE];int bytes_received;while (1) {memset(buffer, 0, BUFFER_SIZE);bytes_received = recv(client->client_fd, buffer, BUFFER_SIZE, 0); if (bytes_received <= 0) { // 客户端断开连接 break; }// 广播消息给所有客户端for (int i = 0; i < MAX_CLIENTS; i++) {if (clients[i].client_fd > 0) {send(clients[i].client_fd, buffer, bytes_received, 0);}}}// 清理客户端信息pthread_mutex_lock(&lock);for (int i = 0; i < MAX_CLIENTS; i++) {if (clients[i].client_fd == client->client_fd) {clients[i].client_fd = 0;num_clients--;break;}}pthread_mutex_unlock(&lock);close(client->client_fd);free(client);return NULL;
}int main() { int server_fd, client_fd; struct sockaddr_in server_addr, client_addr; socklen_t client_addr_len; fd_set readfds, temp_readfds; int max_fd; pthread_t thread_id;// 初始化互斥锁pthread_mutex_init(&lock, NULL);// 创建套接字server_fd = socket(AF_INET, SOCK_STREAM, 0);if (server_fd < 0) {perror("socket creation failed");exit(EXIT_FAILURE);}// 绑定地址和端口memset(&server_addr, 0, sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_addr.s_addr = INADDR_ANY;server_addr.sin_port = htons(12345);if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {perror("bind failed");exit(EXIT_FAILURE);}// 监听if (listen(server_fd, MAX_CLIENTS) < 0) {perror("listen failed");exit(EXIT_FAILURE);}// 初始化fd_setFD_ZERO(&readfds);FD_SET(server_fd, &readfds);max_fd = server_fd;while (1) {temp_readfds = readfds;// select等待就绪文件描述符int activity = select(max_fd + 1, &temp_readfds, NULL, NULL, NULL);if (activity < 0) {perror("select failed");exit(EXIT_FAILURE);}// 检查服务器套接字if (FD_ISSET(server_fd, &temp_readfds)) {client_addr_len = sizeof(client_addr);client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_addr_len);if (client_fd < 0) {perror("accept failed");exit(EXIT_FAILURE);}printf("New client connected, socket fd is %d\n", client_fd);// 添加客户端信息pthread_mutex_lock(&lock);for (int i = 0; i < MAX_CLIENTS; i++) {if (clients[i].client_fd == 0) {clients[i].client_fd = client_fd;clients[i].client_addr = client_addr;num_clients++;break;}}pthread_mutex_unlock(&lock);// 创建线程处理新客户端client_info *new_client = malloc(sizeof(client_info));*new_client = clients[num_clients - 1];pthread_create(&thread_id, NULL, client_handler, (void *)new_client);}}// 清理资源close(server_fd);pthread_mutex_destroy(&lock);return 0;
}

3.3 小结

本章通过两个应用实例展示了select在实际网络编程中的应用。第一个实例是一个简单的echo服务器,它使用select来同时处理多个客户端的连接,并将客户端发送的数据原样返回。第二个实例是一个并发聊天服务器,它不仅使用select来处理多个客户端的连接,还使用多线程来同时处理客户端的消息,实现了广播功能。这些实例展示了select在多客户端网络应用中的强大功能,并为进一步探索网络编程提供了基础。

 

http://www.yayakq.cn/news/206834/

相关文章:

  • 做网站的公司地址企业网站设计布局
  • 专注网站基础优化ui一般用什么软件做
  • 网站开发 工资高吗四方区企业型网站建设
  • 郑州 手机网站网站流量超限什么意思
  • 十堰网站建设是什么2022年十大流行语
  • 网站为什么备案microsoft做网站的
  • 北京网站建设推广网站树状结构图怎么做
  • wordpress全站ajax英文网页如何制作
  • 免费公司主页网站wordpress 传媒主题
  • 怎么增加网站的权重贵港有网站建设的公司吗
  • 自己可以做网站生意好做吗考试类网站如何做
  • 响应式网站后台动漫做暧视频网站
  • 分销网站制作条件wordpress 主题自定义
  • 襄阳做网站的山东饰品行业网站开发
  • 有没有什么网站免费做名片网络维护公司名字
  • 印刷厂网站建设卡片式wordpress模板
  • 房产销售网站设计网页设计模板素材库
  • 建站平台绑定域名房管局网上查询系统
  • 免费的企业建站cmsWordPress实现网址导航
  • 福州城市建设规划网站网站建设能赚钱吗
  • 部署一个网站要做哪些工作营销网站建设推广
  • 西安网站优化排名推广wordpress模板h
  • 如何做原创漫画网站什么值得买 网站开发
  • 做房产销售可以在哪些网站上找客户wordpress错误怎么解决
  • 做直播教程的网站东营今天的消息
  • 北京中交建设公司网站怎么把网站排名到百度前三名
  • 网站做定制还是固定模板北京互联网公司前10强有哪些
  • 建设免费网站北京建设工程继续教育网站
  • cms做视频网站山海关建设局网站
  • 广西住房和城乡建设厅官方网站怎么做公众号网站吗