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

嵌入式第三十九天(TCP多任务并发)

一.TCP服务端并发模型

1.多进程:

进程资源开销大;

安全性高.

#ifndef __HEAD_H__
#define __HEAD_H__#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <arpa/inet.h>
#include <pthread.h>#endif
#include "head.h"#define SER_PORT  50000
#define SER_IP    "192.168.0.179"int init_tcp_ser()
{int sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0){perror("socket error");return -1;}struct sockaddr_in seraddr;seraddr.sin_family = AF_INET;seraddr.sin_port = htons(SER_PORT);seraddr.sin_addr.s_addr = inet_addr(SER_IP);int ret = bind(sockfd, (struct sockaddr *)&seraddr, sizeof(seraddr));if (ret < 0){perror("bind error");return -1;}ret = listen(sockfd, 100);if (ret < 0){perror("listen error");return -1;}return sockfd;
}void wait_handler(int signo)
{wait(NULL);
}int main(int argc, const char *argv[])
{signal(SIGCHLD, wait_handler);struct sockaddr_in cliaddr;socklen_t clilen = sizeof(cliaddr);int sockfd = init_tcp_ser();if (sockfd < 0){return -1;}while (1){int connfd = accept(sockfd, (struct sockaddr *)&cliaddr, &clilen);if (connfd < 0){perror("accept error");return -1;}pid_t pid = fork();if (pid  > 0){}else if (0 == pid){char buff[1024] = {0};while (1){memset(buff, 0, sizeof(buff));size_t cnt = recv(connfd, buff, sizeof(buff), 0);if (cnt < 0){perror("recv error");break;}else if (0 == cnt){printf("[%s : %d] : offline\n", inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port));break;}printf("[%s : %d] : %s\n", inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port), buff);strcat(buff, "---->ok");cnt = send(connfd, buff, strlen(buff), 0);if (cnt < 0){perror("send error");break;}}close(connfd);}}close(sockfd);return 0;
}

2.多线程:

多线程相对于进程资源开销小,相同资源环境下,并发量比进程大.

#include "head.h"#define SER_PORT  50000
#define SER_IP    "192.168.0.179"int init_tcp_ser()
{int sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0){perror("socket error");return -1;}//允许绑定处于TIME_WAIT状态的地址,避免端口占用问题:int optval = 1;setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));struct sockaddr_in seraddr;seraddr.sin_family = AF_INET;seraddr.sin_port = htons(SER_PORT);seraddr.sin_addr.s_addr = inet_addr(SER_IP);int ret = bind(sockfd, (struct sockaddr *)&seraddr, sizeof(seraddr));if (ret < 0){perror("bind error");return -1;}ret = listen(sockfd, 100);if (ret < 0){perror("listen error");return -1;}return sockfd;
}void *task(void *arg)
{char buff[1024] = {0};int connfd = *((int *)arg);while (1){memset(buff, 0, sizeof(buff));size_t cnt = recv(connfd, buff, sizeof(buff), 0);if (cnt < 0){perror("recv error");break;}else if (0 == cnt){printf("offline\n");break;}printf("%s\n", buff);strcat(buff, "---->ok");cnt = send(connfd, buff, strlen(buff), 0);if (cnt < 0){perror("send error");break;}}close(connfd);
}int main(int argc, const char *argv[])
{pthread_t tid;struct sockaddr_in cliaddr;socklen_t clilen = sizeof(cliaddr);int sockfd = init_tcp_ser();if (sockfd < 0){return -1;}while (1){int connfd = accept(sockfd, (struct sockaddr *)&cliaddr, &clilen);if (connfd < 0){perror("accept error");return -1;}pthread_create(&tid, NULL, task, &connfd);pthread_detach(tid);}close(sockfd);return 0;
}

3.线程池:

4.IO多路复用

#ifndef __HEAD_H__
#define __HEAD_H__#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <arpa/inet.h>
#include <pthread.h>
#include <sys/select.h>/* According to earlier standards */
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>#endif
#include "head.h"int main(int argc, const char *argv[])
{mkfifo("./myfifo", 0664);int fd = open("./myfifo", O_WRONLY);if (fd < 0){perror("open fifo error");return -1;}while (1){write(fd, "hello world", 11);sleep(1);}close(fd);return 0;
}
#include "head.h"int main(int argc, const char *argv[])
{char buff[1024] = {0};mkfifo("./myfifo", 0664);int fifofd = open("./myfifo", O_RDONLY);if (fifofd < 0){perror("open fifo error");return -1;}//1 创建文件描述符集合表fd_set rdfds;fd_set rdfdstmp;//2. 清空文件描述符集合表FD_ZERO(&rdfds);//3. 添加关注的文件描述符到集合中FD_SET(0, &rdfds);int maxfd = 0;FD_SET(fifofd, &rdfds);maxfd = maxfd > fifofd ? maxfd : fifofd;while (1){rdfdstmp = rdfds;//4. 传递集合表给内核并等待返回到达事件的结果int cnt = select(maxfd+1, &rdfdstmp, NULL, NULL, NULL);if (cnt < 0){perror("select error");return -1;}if (FD_ISSET(0, &rdfdstmp)){fgets(buff, sizeof(buff), stdin);  //0printf("STDIN : %s\n", buff);}if (FD_ISSET(fifofd, &rdfdstmp)){memset(buff, 0, sizeof(buff));read(fifofd, buff, sizeof(buff));printf("FIFO : %s\n", buff);}}close(fifofd);return 0;
}

5.

相关函数:

#include "head.h"int main(int argc,const char *argv[])
{int sockfd = socket(AF_INET,SOCK_STREAM,0);int optval = 1;setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));if(sockfd < 0){perror("socket error");return -1;}struct sockaddr_in cliaddr;socklen_t clilen = sizeof(cliaddr);struct sockaddr_in seraddr;seraddr.sin_family = AF_INET;seraddr.sin_port = htons(50000);seraddr.sin_addr.s_addr = inet_addr("192.168.19.129");int ret = bind(sockfd,(struct sockaddr*)&seraddr,sizeof(seraddr));if(ret < 0){perror("bind error");return -1;}ret = listen(sockfd,100);if(ret < 0){perror("listen error");return -1;}char buff[1024] = {0};fd_set rdfds;fd_set rdfdstmp;FD_ZERO(&rdfds);FD_SET(sockfd,&rdfds);int maxfd = sockfd;while(1){rdfdstmp = rdfds;int cnt = select(maxfd+1,&rdfdstmp,NULL,NULL,NULL);if(cnt < 0){perror("select error");return -1;}if(FD_ISSET(sockfd,&rdfdstmp)){int connfd = accept(sockfd,(struct sockaddr *)&cliaddr,&clilen);if(connfd < 0){perror("accept error");return -1;;}FD_SET(connfd,&rdfds);maxfd = maxfd > connfd ? maxfd : connfd;}for(int i = sockfd + 1;i <= maxfd;i++){if(FD_ISSET(i,&rdfdstmp)){memset(buff,0,sizeof(buff));ssize_t cnt = recv(i,buff,sizeof(buff),0);if(cnt < 0){perror("recv error");FD_CLR(i,&rdfds);close(i);continue;}else if(0 == cnt){FD_CLR(i,&rdfds);close(i);continue;}printf("%s\n",buff);strcat(buff,"---->ok");cnt = send(i,buff,strlen(buff),0);if(cnt < 0){perror("send error");FD_CLR(i,&rdfds);close(i);continue;}}}}close(sockfd);return 0;
}

http://www.dtcms.com/a/353592.html

相关文章:

  • C语言二级考试环境配置详细教程【mac篇】
  • Java设计模式之《亨元模式》
  • HttpRequest.get()方法报错:301 Moved Permanently
  • XFile v2 系统架构文档
  • Unity List 相关
  • QOpenGLFunctions_2_1 与 OpenGL 的区别
  • 【系统架构设计(四)】软件工程:从瀑布到敏捷的演进之路
  • 【系统架构设计(三)】系统工程与信息系统基础下:企业信息化与电子商务-数字化转型的核心驱动力
  • 【Django + Pure Admin】基于Django+Vue3的前后端分离管理系统框架设计
  • 服务器硬件电路设计之 SPI 问答(六):如何提升服务器硬件电路中的性能?如何强化稳定性?
  • MySQL explain命令的作用
  • 什么是AI+?什么是人工智能+?
  • 济南大学杨波与济南青盟信息技术有限公司杨华伟
  • 北京国标竞品调查,知己知彼(竞品调查研究)
  • Java全栈开发面试实战:从基础到微服务的深度探索
  • Linux学习-TCP并发服务器构建
  • XState
  • 第五章:循环
  • Playwright之脱离元素,页面操作大全!
  • 2026 年美国国际太阳能展(RE+)
  • 如何在 Docker 和AKS上使用 IIS
  • 【Redis 进阶】Redis 典型应用 —— 分布式锁
  • F008 vue+flask 音乐推荐评论和可视化系统+带爬虫前后端分离系统
  • Android中APK包含哪些内容?
  • k8s集群Prometheus部署
  • 【Python办公】快速比较Excel文件中任意两列数据的一致性
  • 【Rust】 1. 变量学习笔记
  • DWT域进行视频信息隐藏的原理及优缺点
  • 洞悉Oracle数据库的基石:深入剖析其核心物理存储结构
  • 2025软件测试面试八股文(完整版)