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

相关文章

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

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

Linux线程之线程的创建、属性、回收、退出、取消方式

《Linux线程之线程的创建、属性、回收、退出、取消方式》文章总结了线程管理核心知识:线程号唯一、创建方式、属性设置(如分离状态与栈大小)、回收机制(join/detach)、退出方法(返回/pthr... 目录1. 线程号2. 线程的创建3. 线程属性4. 线程的回收5. 线程的退出6. 线程的取消7.

Linux下进程的CPU配置与线程绑定过程

《Linux下进程的CPU配置与线程绑定过程》本文介绍Linux系统中基于进程和线程的CPU配置方法,通过taskset命令和pthread库调整亲和力,将进程/线程绑定到特定CPU核心以优化资源分配... 目录1 基于进程的CPU配置1.1 对CPU亲和力的配置1.2 绑定进程到指定CPU核上运行2 基于

golang程序打包成脚本部署到Linux系统方式

《golang程序打包成脚本部署到Linux系统方式》Golang程序通过本地编译(设置GOOS为linux生成无后缀二进制文件),上传至Linux服务器后赋权执行,使用nohup命令实现后台运行,完... 目录本地编译golang程序上传Golang二进制文件到linux服务器总结本地编译Golang程序

Linux下删除乱码文件和目录的实现方式

《Linux下删除乱码文件和目录的实现方式》:本文主要介绍Linux下删除乱码文件和目录的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux下删除乱码文件和目录方法1方法2总结Linux下删除乱码文件和目录方法1使用ls -i命令找到文件或目录

Linux在线解压jar包的实现方式

《Linux在线解压jar包的实现方式》:本文主要介绍Linux在线解压jar包的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux在线解压jar包解压 jar包的步骤总结Linux在线解压jar包在 Centos 中解压 jar 包可以使用 u

linux解压缩 xxx.jar文件进行内部操作过程

《linux解压缩xxx.jar文件进行内部操作过程》:本文主要介绍linux解压缩xxx.jar文件进行内部操作,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、解压文件二、压缩文件总结一、解压文件1、把 xxx.jar 文件放在服务器上,并进入当前目录#

Linux系统性能检测命令详解

《Linux系统性能检测命令详解》本文介绍了Linux系统常用的监控命令(如top、vmstat、iostat、htop等)及其参数功能,涵盖进程状态、内存使用、磁盘I/O、系统负载等多维度资源监控,... 目录toppsuptimevmstatIOStatiotopslabtophtopdstatnmon

在Linux中改变echo输出颜色的实现方法

《在Linux中改变echo输出颜色的实现方法》在Linux系统的命令行环境下,为了使输出信息更加清晰、突出,便于用户快速识别和区分不同类型的信息,常常需要改变echo命令的输出颜色,所以本文给大家介... 目python录在linux中改变echo输出颜色的方法技术背景实现步骤使用ANSI转义码使用tpu

linux hostname设置全过程

《linuxhostname设置全过程》:本文主要介绍linuxhostname设置全过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录查询hostname设置步骤其它相关点hostid/etc/hostsEDChina编程A工具license破解注意事项总结以RHE