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

相关文章

Java并发编程必备之Synchronized关键字深入解析

《Java并发编程必备之Synchronized关键字深入解析》本文我们深入探索了Java中的Synchronized关键字,包括其互斥性和可重入性的特性,文章详细介绍了Synchronized的三种... 目录一、前言二、Synchronized关键字2.1 Synchronized的特性1. 互斥2.

Linux卸载自带jdk并安装新jdk版本的图文教程

《Linux卸载自带jdk并安装新jdk版本的图文教程》在Linux系统中,有时需要卸载预装的OpenJDK并安装特定版本的JDK,例如JDK1.8,所以本文给大家详细介绍了Linux卸载自带jdk并... 目录Ⅰ、卸载自带jdkⅡ、安装新版jdkⅠ、卸载自带jdk1、输入命令查看旧jdkrpm -qa

Linux samba共享慢的原因及解决方案

《Linuxsamba共享慢的原因及解决方案》:本文主要介绍Linuxsamba共享慢的原因及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux samba共享慢原因及解决问题表现原因解决办法总结Linandroidux samba共享慢原因及解决

新特性抢先看! Ubuntu 25.04 Beta 发布:Linux 6.14 内核

《新特性抢先看!Ubuntu25.04Beta发布:Linux6.14内核》Canonical公司近日发布了Ubuntu25.04Beta版,这一版本被赋予了一个活泼的代号——“Plu... Canonical 昨日(3 月 27 日)放出了 Beta 版 Ubuntu 25.04 系统镜像,代号“Pluc

SpringBoot使用OkHttp完成高效网络请求详解

《SpringBoot使用OkHttp完成高效网络请求详解》OkHttp是一个高效的HTTP客户端,支持同步和异步请求,且具备自动处理cookie、缓存和连接池等高级功能,下面我们来看看SpringB... 目录一、OkHttp 简介二、在 Spring Boot 中集成 OkHttp三、封装 OkHttp

Linux安装MySQL的教程

《Linux安装MySQL的教程》:本文主要介绍Linux安装MySQL的教程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux安装mysql1.Mysql官网2.我的存放路径3.解压mysql文件到当前目录4.重命名一下5.创建mysql用户组和用户并修

Linux上设置Ollama服务配置(常用环境变量)

《Linux上设置Ollama服务配置(常用环境变量)》本文主要介绍了Linux上设置Ollama服务配置(常用环境变量),Ollama提供了多种环境变量供配置,如调试模式、模型目录等,下面就来介绍一... 目录在 linux 上设置环境变量配置 OllamPOgxSRJfa手动安装安装特定版本查看日志在

Linux系统之主机网络配置方式

《Linux系统之主机网络配置方式》:本文主要介绍Linux系统之主机网络配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、查看主机的网络参数1、查看主机名2、查看IP地址3、查看网关4、查看DNS二、配置网卡1、修改网卡配置文件2、nmcli工具【通用

Linux系统之dns域名解析全过程

《Linux系统之dns域名解析全过程》:本文主要介绍Linux系统之dns域名解析全过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、dns域名解析介绍1、DNS核心概念1.1 区域 zone1.2 记录 record二、DNS服务的配置1、正向解析的配置

Python异步编程中asyncio.gather的并发控制详解

《Python异步编程中asyncio.gather的并发控制详解》在Python异步编程生态中,asyncio.gather是并发任务调度的核心工具,本文将通过实际场景和代码示例,展示如何结合信号量... 目录一、asyncio.gather的原始行为解析二、信号量控制法:给并发装上"节流阀"三、进阶控制