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

门户网站字体小程序源码开发

门户网站字体,小程序源码开发,网站关键词几个好,网站模板超市端口号快速复用函数 通过getsockopt和setsockopt函数#xff0c;管理套接字的端口号复用设置。具体操作如下#xff1a; getsockopt函数 int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);功能#xff1a;获取套接字的某些选项的属性。…端口号快速复用函数 通过getsockopt和setsockopt函数管理套接字的端口号复用设置。具体操作如下 getsockopt函数 int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);功能获取套接字的某些选项的属性。 参数 sockfd: 套接字描述符。level: 获取的层级例如SOL_SOCKET。optname: 要获取的操作名称如SO_REUSEADDR。optval: 获取的值0表示禁用非0表示启用。optlen: 参数4的大小。 返回值 成功返回0失败返回-1。 setsockopt函数 int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);功能设置套接字的某些选项的属性。 参数 sockfd: 套接字描述符。level: 设置的层级例如SOL_SOCKET。optname: 要设置的操作名称如SO_REUSEADDR。optval: 设置的值0表示禁用非0表示启用。optlen: 参数4的大小。 返回值 成功返回0失败返回-1。 示例代码端口号快速复用 // 获取当前端口号是否能快速复用 int n; int len sizeof(n); getsockopt(oldfd, SOL_SOCKET, SO_REUSEADDR, n, len); if (n 0) {printf(端口号快速复用未启动\n); } else {printf(端口号快速复用已经启动\n); }// 设置当前套接字端口号快速复用 n 999; setsockopt(oldfd, SOL_SOCKET, SO_REUSEADDR, n, sizeof(n));1. 循环服务器模型 描述 循环服务器模型是一次只处理一个客户端请求的传统方式处理完一个客户端请求后才会继续处理下一个客户端请求。由于其效率较低每次只能执行单个任务因此在高并发场景下表现不佳。 在循环服务器模型中服务器端采用了一个循环来不断接收客户端请求。每当一个客户端连接成功后服务器创建一个新的套接字用于通信并处理客户端的请求。每处理完一个客户端请求后服务器继续等待下一个客户端的连接。 主要步骤 创建套接字使用 socket() 函数创建套接字。绑定将套接字与服务器的 IP 地址和端口号绑定。监听开始监听客户端连接请求。循环接收客户端请求 每次 accept() 成功后创建一个新的套接字用于通信。循环收发信息直到客户端断开连接。关闭连接每次客户端断开连接后关闭相应的套接字。 关闭监听套接字 循环服务器代码实现 代码示例 #include myhead.h #define IP 192.168.60.45 #define PORT 6666 #define BACKLOG 20int main(int argc, const char *argv[]) {// 1. 创建套接字int oldfd socket(AF_INET, SOCK_STREAM, 0); // IPV4, TCP协议if (oldfd -1) {perror(socket);return -1;}// 2. 获取端口号属性查看是否启用端口号快速复用int n;int len sizeof(n);if (getsockopt(oldfd, SOL_SOCKET, SO_REUSEADDR, n, len) -1) {perror(getsockopt);return -1;}if (n) {printf(端口号快速复用已经启动\n);} else {printf(端口号快速复用未启动\n);}// 设置端口号快速复用n 999;if (setsockopt(oldfd, SOL_SOCKET, SO_REUSEADDR, n, sizeof(n)) -1) {perror(setsockopt);return -1;}printf(端口号快速复用成功\n);// 3. 绑定IP和端口号struct sockaddr_in server {.sin_family AF_INET, // IPV4.sin_port htons(PORT), // 端口号转换为网络字节序.sin_addr.s_addr inet_addr(IP), // IP地址};if (bind(oldfd, (struct sockaddr *)server, sizeof(server)) -1) {perror(bind);return -1;}// 4. 监听if (listen(oldfd, BACKLOG) -1) {perror(listen);return -1;}// 5. 接受客户端连接请求并创建新的描述符用于通信struct sockaddr_in client;socklen_t client_len sizeof(client);int newfd;while (1) {newfd accept(oldfd, (struct sockaddr *)client, client_len);if (newfd -1) {perror(accept);return -1;}printf(%s发来连接请求\n, inet_ntoa(client.sin_addr));// 6. 循环收发信息char buff[1024];while (1) {memset(buff, 0, sizeof(buff));int len recv(newfd, buff, sizeof(buff), 0); // 接收客户端信息if (len 0) { // 客户端断开连接printf(客户端下线\n);break;}printf(%s\n, buff);strcat(buff, 5201314); // 添加回复信息send(newfd, buff, sizeof(buff), 0); // 发送信息}}// 关闭套接字close(oldfd);close(newfd);return 0; }代码流程 创建套接字socket() 函数创建一个 TCP 套接字。设置端口号复用通过 setsockopt() 设置端口复用允许在同一端口上建立多个连接。绑定使用 bind() 将套接字与 IP 地址和端口绑定。监听调用 listen() 使套接字进入监听状态准备接受客户端连接。接受连接通过 accept() 接受客户端连接返回一个新的套接字描述符用于与客户端通信。收发消息在循环内通过 recv() 接收客户端消息然后用 send() 发送回应消息。直到客户端断开连接。关闭套接字处理完成后关闭套接字。 缺点 同步阻塞当前的设计是同步阻塞的服务器在处理一个客户端请求时不能同时处理其他客户端的请求。因此如果有多个客户端连接必须等待前一个客户端的请求处理完成后才能继续。客户端阻塞新客户端要通信时必须等到旧客户端退出。服务器只能在当前连接断开后接受新的客户端请求。新客户端要通信时必须等待旧客户端退出。 改进 为了解决这个问题可以采用 多线程 或 多进程 模型来并发处理客户端请求从而避免客户端之间的阻塞。 2. 基于TCP的并发服务器 2.1 多进程并发服务器 多进程并发服务器的模型通常由一个父进程负责监听客户端的连接请求每当接收到一个连接请求时父进程创建一个新的子进程来处理与客户端的通信。父进程和子进程之间通过文件描述符传递数据。父进程负责监听和接收客户端连接子进程则处理数据收发。 多进程服务器模型的关键问题 1. 子进程在哪创建 父进程在接收到客户端的连接请求时会创建一个子进程来处理该请求。 示例代码 pid_t pid fork(); if (pid 0) {// 父进程继续监听新的连接请求关闭新文件描述符close(newfd); } else if (pid 0) {// 子进程关闭旧的监听套接字并处理客户端通信close(server_fd);// 与客户端通信...close(newfd); // 处理完成后关闭与客户端的连接exit(0); // 子进程处理完请求后退出 } else {perror(fork);return -1; }2. 子进程怎么回收子进程处理完任务后会退出因此需要确保父进程能够回收已经退出的子进程防止僵尸进程的产生。 常见的方式 阻塞回收父进程使用 wait() 或 waitpid() 函数在子进程退出时阻塞等待并回收它们。非阻塞回收如果不想让父进程被 wait() 阻塞可以使用信号处理机制通过捕捉 SIGCHLD 信号并在信号处理函数中回收子进程。 示例代码非阻塞回收 // 信号处理函数用于回收僵尸进程 void handle_sigchld(int sig) {while (waitpid(-1, NULL, WNOHANG) 0); // 回收已退出的子进程 }// 在主程序中捕捉 SIGCHLD 信号 signal(SIGCHLD, handle_sigchld);3. 文件描述符 由于系统对打开的文件描述符有限制因此需要确保在父子进程中正确管理文件描述符。 在操作系统中文件描述符是有限的每个进程可以打开的文件包括套接字的数量是有限的。如果服务器并发连接数较多且每个连接都创建一个新的子进程就可能遇到文件描述符耗尽的问题。可以通过以下方式解决或避免这一问题 解决方案 增加文件描述符限制可以通过 ulimit -n 命令临时增加系统的文件描述符限制或者在 /etc/security/limits.conf 文件中永久增加限制。使用线程池或连接池而不是为每个客户端创建一个新的子进程可以通过线程池或连接池来管理客户端连接。多线程或线程池模型可以减少系统开销因为线程的创建和销毁比进程更加轻量。复用文件描述符通过一些技术手段例如 select()、poll() 或 epoll()来管理多个连接不需要为每个客户端创建一个独立的进程或线程从而避免耗尽文件描述符。 示例修改文件描述符限制 临时修改文件描述符的限制 ulimit -n 65535永久修改文件描述符的限制 在 /etc/security/limits.conf 文件中添加  * soft nofile 65535 * hard nofile 65535总结 子进程创建父进程在接收到客户端连接请求后使用 fork() 创建子进程来处理该客户端的通信。子进程回收父进程可以通过 wait() 或 waitpid() 回收子进程也可以通过信号处理函数来非阻塞回收已退出的子进程。文件描述符限制多进程模型可能会受到系统文件描述符限制的影响解决方法包括增加文件描述符限制、使用线程池或连接池等技术来减少文件描述符的占用。 多进程并发服务器执行模型 定义信号处理函数非阻塞回收僵尸进程。 绑定子进程退出时的信号。 创建套接字绑定监听循环接收客户端连接让父进程接收客户端请求并关闭新文件描述符子进程关闭旧的描述符只负责数据收发。 多进程服务器代码 #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 signal.h #include wait.h#define IP 192.168.60.45 #define PORT 6666 #define BACKLOG 100// 信号处理函数用于回收僵尸进程 void fun(int sss) {if (sss SIGCHLD){while (waitpid(-1, NULL, 0) 0); // 循环回收子进程} }int main(int argc, const char *argv[]) {// 1. 捕获子进程退出时的信号if (signal(SIGCHLD, fun) SIG_ERR){perror(signal);return -1;}// 2. 创建TCP类型的套接字int oldfd socket(AF_INET, SOCK_STREAM, 0);if (oldfd -1){perror(socket);return -1;}// 3. 设置端口号快速复用int n 1;if (setsockopt(oldfd, SOL_SOCKET, SO_REUSEADDR, n, sizeof(n)) -1){perror(setsockopt);return -1;}printf(端口号快速复用成功\n);// 4. 绑定struct sockaddr_in server {.sin_family AF_INET,.sin_port htons(PORT),.sin_addr.s_addr inet_addr(IP),};if (bind(oldfd, (struct sockaddr *)server, sizeof(server)) -1){perror(bind);return -1;}// 5. 监听if (listen(oldfd, BACKLOG) -1){perror(listen);return -1;}struct sockaddr_in client;socklen_t client_len sizeof(client);char buff[1024];// 6. 主循环接收客户端连接while (1){int newfd accept(oldfd, (struct sockaddr *)client, client_len); // 接收客户端连接printf(%s发来连接请求\n, inet_ntoa(client.sin_addr));pid_t pid fork(); // 创建子进程if (pid 0) // 父进程监听并关闭新的描述符{close(newfd);}else if (pid 0) // 子进程处理数据收发{close(oldfd); // 子进程关闭旧的描述符while (1){int len recv(newfd, buff, sizeof(buff), 0);if (len 0){printf(客户端退出\n);break;}printf(客户端%s发来消息%s\n, inet_ntoa(client.sin_addr), buff);strcat(buff, inet_ntoa(client.sin_addr)); // 回去时加上客户端IPsend(newfd, buff, sizeof(buff), 0);}close(newfd);exit(0); // 子进程退出}else{perror(fork);return -1;}}return 0; }客户端代码 客户端通过连接到服务器来发送数据并接收服务器的响应。该程序创建一个TCP套接字连接到指定的服务器IP和端口并与服务器进行数据交互。 #include myhead.h#define IP 192.168.60.45 #define PORT 6666int main(int argc, const char *argv[]) {// 1. 创建套接字int oldfd socket(AF_INET, SOCK_STREAM, 0);if (oldfd -1){perror(socket);return -1;}// 2. 连接服务器struct sockaddr_in server {.sin_family AF_INET,.sin_port htons(PORT),.sin_addr.s_addr inet_addr(IP),};if (connect(oldfd, (struct sockaddr *)server, sizeof(server)) -1){perror(connect);return -1;}// 3. 数据收发char buff[1024];while (1){fgets(buff, sizeof(buff), stdin); // 键盘输入字符串buff[strlen(buff) - 1] \0; // 去除换行符// 发送数据到服务器send(oldfd, buff, sizeof(buff), 0);// 接收服务器数据int len recv(oldfd, buff, sizeof(buff), 0);if (len 0){printf(服务器意外退出\n);break;}printf(接收服务器消息%s\n, buff);}// 关闭套接字close(oldfd);return 0; }总结 多进程并发模型 通过父进程监听和创建子进程来处理每个客户端的请求使用fork创建子进程在子进程中负责数据收发父进程关闭新文件描述符子进程关闭旧文件描述符。通过信号处理函数回收子进程避免僵尸进程。TCP客户端 连接到服务器后通过套接字发送数据并接收响应支持实时数据交互。 这种模型适用于客户端和服务器之间的实时通信特别是在需要处理多个客户端请求的场景中。 2.2 多线程并发服务器 1. 多线程的优势 资源开销小线程的资源开销比进程小创建和销毁线程的速度比进程快。响应速度快如果客户端连接较多可以通过线程池提前创建线程来分配给客户端减少响应延迟。线程销毁开销小线程占用资源较少销毁线程的资源开销也较小。 2. 服务器模型 主线程负责监听客户端连接。子线程负责接收和发送数据与客户端通信。 3. 服务器的工作流程 创建原始套接字使用 socket() 创建一个 TCP 类型的套接字。绑定 IP 地址和端口号使用 bind() 绑定服务器的 IP 地址和端口。监听客户端连接使用 listen() 开始监听客户端的连接请求。接收客户端连接使用 accept() 接收客户端的连接请求并为每个客户端创建一个新线程。线程处理客户端请求每个线程接收到客户端消息后进行处理并发送响应。线程执行完后退出。 4. 线程池 为了处理大量并发请求线程池的机制可以预先创建一定数量的线程接收到客户端请求时从线程池中取出一个线程来处理该请求。 5. 代码实现 #include myhead.h// 定义服务器的 IP 地址、端口号和最大连接数 #define IP 192.168.60.45 #define PORT 9999 #define BACKLOG 10// 定义结构体用于传递客户端信息和新文件描述符 typedef struct {struct sockaddr_in client; // 客户端信息int newfd; // 新的文件描述符 } ZYJ;// 线程体函数处理与客户端的通信 void *fun(void *sss) {// 获取新文件描述符和客户端信息int newfd ((ZYJ *)sss)-newfd;struct sockaddr_in client ((ZYJ *)sss)-client;// 打印客户端的 IP 地址printf(%s发来信息\n, inet_ntoa(client.sin_addr));char buff[1024];while (1) {// 接收客户端发来的消息int len recv(newfd, buff, sizeof(buff), 0);if (len 0) { // 客户端退出printf(客户端退出\n);break;}// 打印收到的消息printf(收到消息%s\n, buff);// 在消息末尾加上 1973strcat(buff, 1973);// 将处理后的消息发送回客户端send(newfd, buff, sizeof(buff), 0);}// 线程结束时退出pthread_exit(NULL); }int main(int argc, const char *argv[]) {// 1. 创建套接字int oldfd socket(AF_INET, SOCK_STREAM, 0);if (oldfd -1) {perror(socket);return -1;}// 2. 绑定 IP 地址和端口号struct sockaddr_in server {.sin_family AF_INET,.sin_port htons(PORT),.sin_addr.s_addr inet_addr(IP),};if (bind(oldfd, (struct sockaddr *)server, sizeof(server)) -1) {perror(bind);return -1;}// 3. 监听客户端的连接请求if (listen(oldfd, BACKLOG) -1) {perror(listen);return -1;}struct sockaddr_in client;socklen_t client_len sizeof(client);// 4. 主线程循环接收客户端连接while (1) {int newfd accept(oldfd, (struct sockaddr *)client, client_len); // 接收客户端连接请求ZYJ sb;sb.newfd newfd; // 保存新的文件描述符sb.client client; // 保存客户端信息pthread_t tid;// 5. 创建子线程处理客户端请求tid pthread_create(tid, NULL, fun, sb);if (tid -1) {perror(pthread_create);return -1;}// 6. 将线程设为分离状态系统会自动回收线程资源pthread_detach(tid);}return 0; }代码功能 创建套接字通过 socket() 创建一个 TCP 套接字。绑定 IP 地址和端口通过 bind() 将套接字绑定到指定的 IP 地址和端口号。监听连接调用 listen() 开始监听来自客户端的连接请求最多允许 BACKLOG 个连接排队。接受连接主线程通过 accept() 接收客户端的连接请求并返回一个新的文件描述符 newfd 用于与客户端进行通信。创建子线程每当接受到新的连接主线程会通过 pthread_create() 创建一个子线程处理客户端的消息传递和接收。每个子线程的处理逻辑通过 fun() 函数完成。线程回收通过 pthread_detach() 将线程设置为分离状态子线程在完成后会自动回收资源避免主线程等待子线程退出。 关键函数 socket()创建一个套接字。bind()将套接字与本地的 IP 地址和端口号绑定。listen()让套接字进入监听状态准备接受客户端连接。accept()阻塞等待客户端连接并返回一个新的套接字用于与客户端通信。pthread_create()创建新的线程来处理客户端请求。pthread_detach()将线程设为分离状态线程结束后自动回收资源。recv()接收客户端发送的消息。send()向客户端发送消息。 适用场景 这个多线程模型适用于客户端连接量较大或较为频繁的场景。每个客户端连接都会分配一个线程进行处理因此可以在短时间内处理多个客户端的请求。 线程池优化 虽然该程序为每个连接创建了一个独立的线程但在实际应用中为了提高资源利用率和性能可以引入线程池。线程池事先创建好一组线程客户端请求到来时从线程池中取出一个线程来处理而不是每次都创建一个新的线程。这样可以减少线程的创建和销毁开销。 注意事项 多线程同步问题虽然本例中没有涉及多线程之间的共享资源但在复杂应用中可能需要考虑线程同步机制如互斥锁、条件变量等。线程回收线程被设为分离状态pthread_detach()这样可以在线程结束后由系统自动回收资源而不需要调用 pthread_join()。 总结 该程序展示了一个典型的多线程并发服务器模型使用线程处理每个客户端请求减少了主线程的负担提高了处理效率。通过 pthread_detach() 来自动回收资源避免了线程泄露问题。 6.  客户端代码示例 #include myhead.h#define IP 192.168.60.45 #define PORT 9999int main(int argc, const char *argv[]) {// 1、创建套接字int oldfd socket(AF_INET, SOCK_STREAM, 0);if (oldfd -1){perror(socket);return -1;}// 2、连接服务器struct sockaddr_in server {.sin_family AF_INET,.sin_port htons(PORT),.sin_addr.s_addr inet_addr(IP),};if (connect(oldfd, (struct sockaddr *)server, sizeof(server)) -1){perror(connect);return -1;}// 3、数据收发char buff[1024];while (1){fgets(buff, sizeof(buff), stdin); // 键盘输入字符串buff[strlen(buff) - 1] \0; // 去除换行符// 发送数据到服务器send(oldfd, buff, sizeof(buff), 0);// 接收服务器数据int len recv(oldfd, buff, sizeof(buff), 0);if (len 0){printf(服务器意外退出\n);break;}printf(接收服务器消息%s\n, buff);}// 关闭套接字close(oldfd);return 0; }
http://www.hkea.cn/news/14507411/

相关文章:

  • 陕西省信用建设门户网站服务好的扬中网站优化
  • 网站被同行抄袭怎么办河南旅游网页设计
  • c 2015 做网站优班图搭建网站
  • WordPress一键开启全站SSL当当网站建设与易趣网站对比
  • 做网站需要编程么响应式网站设计图怎么做
  • 网站app怎么制作教程凡科网免费建站步骤及视频
  • 网站推广的正确方式做高仿网站有哪些
  • 成都网站建设那家好怎样做自己可以发布消息的网站
  • 平板购物网站建设建设国外网站引流吗
  • 网站建设的方案计划企业标准
  • 徽石网站建设万户信息 做网站怎么样
  • 佛山哪有网站建设公司手机网站页面尺寸大小
  • 设置字体颜色的网站毕业设计网站怎么做
  • 建设网站需要什么技术支持泰安网站建设怎么样
  • 中山做网站排名做app的网站
  • 公司网站在哪里做快速搭建网站模板
  • 网站色彩搭配表适合初学者做的网页
  • 昆山网站建设公司怎么样wordpress 不能查看站点
  • 电子商务学网站建设好吗网站权重一般有几个等级
  • codeorg免费编程网站贵州省住房与城乡建设厅网站
  • 做自媒体网站开发做网站工资怎么样
  • 无锡前洲行业网站建设半瓶的wordpress之旅
  • 广州企业网站模板建站2024年还有新冠吗
  • 天津网站建立seo教程免费分享
  • 携程的网站建设石家庄网站建设流程
  • 山东莱州市建设局网站有没有专门帮人推广的公司
  • 陕西的网站建设公司排名网站建设平台官网河间米各庄
  • 大连网站设计公司wordpress自学
  • 太平洋建设 网站深圳极速网站建设电话
  • 设计行业网站泰安抖音seo