嵌入式学习Day36---Linux软件编程---网络编程

2024-08-21 02:52

本文主要是介绍嵌入式学习Day36---Linux软件编程---网络编程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

一、TCP并发模型

1.1.阻塞IO

1.2.非阻塞IO

1.步骤

2.函数接口

3.实例

1.3.异步IO

1.步骤

2.函数接口

3.实例

1.4.多路复用IO 

1.select

函数接口:

实例 

2.poll

3.epoll

 二、总结


 

一、TCP并发模型

1.1.阻塞IO

 CPU占用率低,等待资源时将任务挂起,不占用CPU资源,等到拿到资源后继续向下执行;

1.2.非阻塞IO

 能够让任务不阻塞,效率低,因为没有数据时,CPU一直空转;

1.步骤

        1)获取文件描述符的IO状态

        2)设置文件描述符的IO状态为非阻塞

        3) 将该IO状态写入文件描述符

2.函数接口

        fctnl() 具体使用看下面的例子

3.实例

        此处,以写入端通过管道向接收端传递信息,接收端可以接收管道信息,并且也可以从终端接收。将管道和终端的描述符均设置为非阻塞,实现,接收端一边可以接收写入端的信息,一边可以接收终的信息。(核心在read.c)

write.c

#include "../head.h"int main(void)
{int fd = 0;int ret = 0;ssize_t nsize = 0;char buff[1024] = {0};mkfifo("/tmp/myfifo", 0664);fd = open("/tmp/myfifo", O_WRONLY);if (fd == -1){perror("open");return -1;}while(1){memset(buff, 0, sizeof(buff));gets(buff);nsize = write(fd, buff, strlen(buff)+1);if (nsize == -1){perror("write");return -1;}}close(fd);return 0;
}

 read.c

#include "../head.h"int main(void)
{   int fd = 0;int flag = 0;ssize_t nsize = 0;char *pnisze = NULL;char buf[1024] = {0};mkfifo("/tmp/myfifo", 0664);fd = open("/tmp/myfifo", O_RDONLY);if (-1 == fd){perror("fail to open");return -1;}//获得文件描述符的熟悉flag = fcntl(fd, F_GETFL);//设置文件描述符为非阻塞flag |= O_NONBLOCK;//设置文件描述符fcntl(fd, F_SETFL, flag);/*设置终端IO*/flag = fcntl(0, F_GETFL);flag |= O_NONBLOCK;fcntl(0, F_SETFL, flag);while (1){memset(buf, 0, sizeof(buf));nsize = read(fd, buf, sizeof(buf));if (nsize > 0){printf("WRITE = %s\n", buf);}memset(buf, 0, sizeof(buf));pnisze = gets(buf);if (pnisze != NULL){printf("STDIN = %s\n", buf);}}close(fd);return 0;
}

1.3.异步IO

        将一个文件描述符设定为异步IO,当IO有事件发生时,内核会向用户层发送SIGIO信号提醒用户层处理事件  

1.步骤

        1)获取文件描述符的IO状态

        2)设置文件描述符的IO状态为异步

        3) 将该IO状态写入文件描述符

        4)处理IO信号

2.函数接口

        fctnl() 具体使用看下面的例子

        signal(SIGIO, handel); 接收文件描述符信号 

3.实例

        此处,以写入端通过管道向接收端传递信息,接收端可以接收管道信息,并且也可以从终端接收。将管道描述符设置为异步,终端信息正常接收,当管道里面有了一个信息时,发送SIGIO信号。(核心在read.c)

write.c

#include "../head.h"int main(void)
{int fd = 0;int ret = 0;ssize_t nsize = 0;char buff[1024] = {0};mkfifo("/tmp/myfifo", 0664);fd = open("/tmp/myfifo", O_WRONLY);if (fd == -1){perror("open");return -1;}while(1){memset(buff, 0, sizeof(buff));gets(buff);nsize = write(fd, buff, strlen(buff)+1);if (nsize == -1){perror("write");return -1;}}close(fd);return 0;
}

read.c

#include "../head.h"int fd = 0;
void handler(int sig)
{char tmpbuff[1024] = {0};memset(tmpbuff, 0, sizeof(tmpbuff));read(fd, tmpbuff, sizeof(tmpbuff));printf("RECV:%s\n", tmpbuff);
}
int main(void)
{   int flag = 0;ssize_t nsize = 0;char *pnisze = NULL;char buf[1024] = {0};mkfifo("/tmp/myfifo", 0664);fd = open("/tmp/myfifo", O_RDONLY);if (-1 == fd){perror("fail to open");return -1;}//获取管道的IO状态flag = fcntl(fd, F_GETFL);//设置为异步flag |= O_ASYNC;fcntl(fd, F_SETFL, flag);//通知当前进程管道信号来了fcntl(fd, F_SETOWN, getpid());signal(SIGIO, handler);while (1){memset(buf, 0, sizeof(buf));pnisze = gets(buf);if (pnisze != NULL){printf("STDIN = %s\n", buf);}}close(fd);return 0;
}

 

1.4.多路复用IO 

1.select

函数接口:
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);功能:监听文件描述符是否有事件发生参数:nfds:最大文件描述符的值 + 1 readfds:读文件描述符集合writefds:写文件描述符集合exceptfds:异常文件描述符集合timeout:超时时间返回值:成功返回产生事件的文件描述符个数失败返回-1 timeout时间到达仍然没有产生的事件返回0 
        void FD_CLR(int fd, fd_set *set);功能:将fd从集合中清除int  FD_ISSET(int fd, fd_set *set);功能:判断fd是否仍在文件描述符集合中void FD_SET(int fd, fd_set *set);功能:将fd加入文件描述符集合中void FD_ZERO(fd_set *set);功能:将文件描述符集合清0 
实例 

client.c

#include "head.h"int CreateTcpConnection(const char *pip, int port)
{int sockfd = 0;int ret = 0;struct sockaddr_in seraddr;seraddr.sin_family = AF_INET;seraddr.sin_port = htons(port);seraddr.sin_addr.s_addr = inet_addr(pip);sockfd = socket(AF_INET, SOCK_STREAM, 0);if (-1 == sockfd){return -1;}ret = connect(sockfd, (struct sockaddr *)&seraddr, sizeof(seraddr));if (-1 == ret){return -1;}return sockfd;
}int HandleConnection(int sockfd)
{char tmpbuff[4096] = {0};static int cnt = 0;ssize_t nsize = 0;sprintf(tmpbuff, "hello world --- %d", cnt);nsize = send(sockfd, tmpbuff, strlen(tmpbuff), 0);if (-1 == nsize){return -1;}cnt++;memset(tmpbuff, 0, sizeof(tmpbuff));nsize = recv(sockfd, tmpbuff, sizeof(tmpbuff), 0);  if (-1 == nsize){return -1;}else if (0 == nsize){return 0;}printf("RECV:%s\n", tmpbuff);return nsize;
}int main(void)
{int sockfd = 0;int ret = 0;sockfd = CreateTcpConnection(SER_IP, SER_PORT);if (-1 == sockfd){printf("连接服务器异常\n");return -1;}while (1){ret = HandleConnection(sockfd);if (-1 == ret){printf("连接出错!\n");break;}else if (0 == ret){printf("连接关闭\n");break;}sleep(1);}close(sockfd);return 0;
}

server.c

#include "head.h"int CreateListenSocket(const char *pip, int port)
{int sockfd = 0;int ret = 0;struct sockaddr_in seraddr;sockfd = socket(AF_INET, SOCK_STREAM, 0);if (-1 == sockfd){return -1;}seraddr.sin_family = AF_INET;seraddr.sin_port = htons(port);seraddr.sin_addr.s_addr = inet_addr(pip);ret = bind(sockfd, (struct sockaddr *)&seraddr, sizeof(seraddr));if (-1 == ret){return -1;}ret = listen(sockfd, 10);if (-1 == ret){return -1;}return sockfd;
}int HandleConnection(int confd)
{char tmpbuff[4096] = {0};ssize_t nsize = 0;nsize = recv(confd, tmpbuff, sizeof(tmpbuff), 0);if (-1 == nsize){return -1;}else if (0 == nsize){return 0;}printf("RECV:%s\n", tmpbuff);sprintf(tmpbuff, "%s --- echo", tmpbuff);nsize = send(confd, tmpbuff, strlen(tmpbuff), 0);if (-1 == nsize){return -1;}return nsize;
}int main(void)
{int sockfd = 0;int confd = 0;int ret = 0;fd_set rdfds;fd_set tmpfds;int nready = 0;int maxfd = 0;int i = 0;//创建监听套接字sockfd = CreateListenSocket(SER_IP, SER_PORT);if (-1 == sockfd){printf("创建监听套接字失败\n");return -1;}//将sockfd加入监听集合中FD_ZERO(&rdfds);FD_SET(sockfd, &rdfds);maxfd = sockfd;while (1){//开始监听tmpfds = rdfds;nready = select(maxfd+1, &tmpfds, NULL, NULL, NULL);if (-1 == nready){perror("fail to select");return -1;}//如果sockfd产生事件,处理新的连接请求,并将新的文件描述符加入集合,下次一起监听if (FD_ISSET(sockfd, &tmpfds)){confd = accept(sockfd, NULL, NULL);if (-1 == confd){FD_CLR(sockfd, &rdfds);close(sockfd);continue;}   maxfd = maxfd > confd ? maxfd : confd;FD_SET(confd, &rdfds);}//遍历所有已经连接的客户端中是否有事件发生for (i = sockfd+1; i <= maxfd; i++){if (FD_ISSET(i, &tmpfds)){ret = HandleConnection(i);if (-1 == ret){printf("连接异常\n");FD_CLR(i, &rdfds);close(i);continue;}else if (0 == ret){printf("连接断开\n");FD_CLR(i, &rdfds);close(i);continue;}}}}close(sockfd);return 0;
}

2.poll

3.epoll

 二、总结

        2024年8月20日,学习的第36天。今天主要学习TCP的并发模型,主要学习如何模拟实现现实中统一服务器可以和好多不同的客户端同时交互。

        加油!

这篇关于嵌入式学习Day36---Linux软件编程---网络编程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1091914

相关文章

Oracle数据库定时备份脚本方式(Linux)

《Oracle数据库定时备份脚本方式(Linux)》文章介绍Oracle数据库自动备份方案,包含主机备份传输与备机解压导入流程,强调需提前全量删除原库数据避免报错,并需配置无密传输、定时任务及验证脚本... 目录说明主机脚本备机上自动导库脚本整个自动备份oracle数据库的过程(建议全程用root用户)总结

Linux如何查看文件权限的命令

《Linux如何查看文件权限的命令》Linux中使用ls-R命令递归查看指定目录及子目录下所有文件和文件夹的权限信息,以列表形式展示权限位、所有者、组等详细内容... 目录linux China编程查看文件权限命令输出结果示例这里是查看tomcat文件夹总结Linux 查看文件权限命令ls -l 文件或文件夹

idea的终端(Terminal)cmd的命令换成linux的命令详解

《idea的终端(Terminal)cmd的命令换成linux的命令详解》本文介绍IDEA配置Git的步骤:安装Git、修改终端设置并重启IDEA,强调顺序,作为个人经验分享,希望提供参考并支持脚本之... 目录一编程、设置前二、前置条件三、android设置四、设置后总结一、php设置前二、前置条件

Linux系统中查询JDK安装目录的几种常用方法

《Linux系统中查询JDK安装目录的几种常用方法》:本文主要介绍Linux系统中查询JDK安装目录的几种常用方法,方法分别是通过update-alternatives、Java命令、环境变量及目... 目录方法 1:通过update-alternatives查询(推荐)方法 2:检查所有已安装的 JDK方

Linux系统之lvcreate命令使用解读

《Linux系统之lvcreate命令使用解读》lvcreate是LVM中创建逻辑卷的核心命令,支持线性、条带化、RAID、镜像、快照、瘦池和缓存池等多种类型,实现灵活存储资源管理,需注意空间分配、R... 目录lvcreate命令详解一、命令概述二、语法格式三、核心功能四、选项详解五、使用示例1. 创建逻

Linux下在线安装启动VNC教程

《Linux下在线安装启动VNC教程》本文指导在CentOS7上在线安装VNC,包含安装、配置密码、启动/停止、清理重启步骤及注意事项,强调需安装VNC桌面以避免黑屏,并解决端口冲突和目录权限问题... 目录描述安装VNC安装 VNC 桌面可能遇到的问题总结描js述linux中的VNC就类似于Window

linux下shell脚本启动jar包实现过程

《linux下shell脚本启动jar包实现过程》确保APP_NAME和LOG_FILE位于目录内,首次启动前需手动创建log文件夹,否则报错,此为个人经验,供参考,欢迎支持脚本之家... 目录linux下shell脚本启动jar包样例1样例2总结linux下shell脚本启动jar包样例1#!/bin

Linux之platform平台设备驱动详解

《Linux之platform平台设备驱动详解》Linux设备驱动模型中,Platform总线作为虚拟总线统一管理无物理总线依赖的嵌入式设备,通过platform_driver和platform_de... 目录platform驱动注册platform设备注册设备树Platform驱动和设备的关系总结在 l

linux批量替换文件内容的实现方式

《linux批量替换文件内容的实现方式》本文总结了Linux中批量替换文件内容的几种方法,包括使用sed替换文件夹内所有文件、单个文件内容及逐行字符串,强调使用反引号和绝对路径,并分享个人经验供参考... 目录一、linux批量替换文件内容 二、替换文件内所有匹配的字符串 三、替换每一行中全部str1为st

Linux进程CPU绑定优化与实践过程

《Linux进程CPU绑定优化与实践过程》Linux支持进程绑定至特定CPU核心,通过sched_setaffinity系统调用和taskset工具实现,优化缓存效率与上下文切换,提升多核计算性能,适... 目录1. 多核处理器及并行计算概念1.1 多核处理器架构概述1.2 并行计算的含义及重要性1.3 并