嵌入式学习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

相关文章

MySQL的JDBC编程详解

《MySQL的JDBC编程详解》:本文主要介绍MySQL的JDBC编程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录前言一、前置知识1. 引入依赖2. 认识 url二、JDBC 操作流程1. JDBC 的写操作2. JDBC 的读操作总结前言本文介绍了mysq

防止Linux rm命令误操作的多场景防护方案与实践

《防止Linuxrm命令误操作的多场景防护方案与实践》在Linux系统中,rm命令是删除文件和目录的高效工具,但一旦误操作,如执行rm-rf/或rm-rf/*,极易导致系统数据灾难,本文针对不同场景... 目录引言理解 rm 命令及误操作风险rm 命令基础常见误操作案例防护方案使用 rm编程 别名及安全删除

Linux下MySQL数据库定时备份脚本与Crontab配置教学

《Linux下MySQL数据库定时备份脚本与Crontab配置教学》在生产环境中,数据库是核心资产之一,定期备份数据库可以有效防止意外数据丢失,本文将分享一份MySQL定时备份脚本,并讲解如何通过cr... 目录备份脚本详解脚本功能说明授权与可执行权限使用 Crontab 定时执行编辑 Crontab添加定

使用docker搭建嵌入式Linux开发环境

《使用docker搭建嵌入式Linux开发环境》本文主要介绍了使用docker搭建嵌入式Linux开发环境,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录1、前言2、安装docker3、编写容器管理脚本4、创建容器1、前言在日常开发全志、rk等不同

Debian 13升级后网络转发等功能异常怎么办? 并非错误而是管理机制变更

《Debian13升级后网络转发等功能异常怎么办?并非错误而是管理机制变更》很多朋友反馈,更新到Debian13后网络转发等功能异常,这并非BUG而是Debian13Trixie调整... 日前 Debian 13 Trixie 发布后已经有众多网友升级到新版本,只不过升级后发现某些功能存在异常,例如网络转

linux系统上安装JDK8全过程

《linux系统上安装JDK8全过程》文章介绍安装JDK的必要性及Linux下JDK8的安装步骤,包括卸载旧版本、下载解压、配置环境变量等,强调开发需JDK,运行可选JRE,现JDK已集成JRE... 目录为什么要安装jdk?1.查看linux系统是否有自带的jdk:2.下载jdk压缩包2.解压3.配置环境

Linux搭建ftp服务器的步骤

《Linux搭建ftp服务器的步骤》本文给大家分享Linux搭建ftp服务器的步骤,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录ftp搭建1:下载vsftpd工具2:下载客户端工具3:进入配置文件目录vsftpd.conf配置文件4:

Python异步编程之await与asyncio基本用法详解

《Python异步编程之await与asyncio基本用法详解》在Python中,await和asyncio是异步编程的核心工具,用于高效处理I/O密集型任务(如网络请求、文件读写、数据库操作等),接... 目录一、核心概念二、使用场景三、基本用法1. 定义协程2. 运行协程3. 并发执行多个任务四、关键

Linux实现查看某一端口是否开放

《Linux实现查看某一端口是否开放》文章介绍了三种检查端口6379是否开放的方法:通过lsof查看进程占用,用netstat区分TCP/UDP监听状态,以及用telnet测试远程连接可达性... 目录1、使用lsof 命令来查看端口是否开放2、使用netstat 命令来查看端口是否开放3、使用telnet

Linux系统管理与进程任务管理方式

《Linux系统管理与进程任务管理方式》本文系统讲解Linux管理核心技能,涵盖引导流程、服务控制(Systemd与GRUB2)、进程管理(前台/后台运行、工具使用)、计划任务(at/cron)及常用... 目录引言一、linux系统引导过程与服务控制1.1 系统引导的五个关键阶段1.2 GRUB2的进化优