linux 全双工 wifi热点,Linux中的同时套接字读/写(“全双工”)(特别是aio)

我正在移植构建在ACE Proactor框架之上的应用程序.该应用程序适用于VxWorks和Windows,但在使用librt的内核2.6.X.X的Linux(CentOS 5.5,WindRiver Linux 1.4和3.0)上无法运行.

我把问题缩小到一个非常基本的问题:

应用程序在套接字上开始异步(通过aio_read)读取操作,然后在同一个套接字上开始异步(通过aio_write)写入.由于协议是从应用程序结束初始化的,因此无法实现读取操作.

– 当套接字处于阻塞模式时,永远不会写入并且协议“挂起”.

– 使用O_NONBLOCK套接字时,写入成功,但读取无限期地返回“EWOULDBLOCK / EAGAIN”错误,永远不会恢复(即使重新启动AIO操作).

我经历了多个论坛,无法找到一个明确的答案,说明这是否应该可行(而且我做错了)或Linux AIO不可能.是否可以放弃AIO并寻求不同的实现(通过epoll / poll / select等)?

附件是一个示例代码,可以在非阻塞套接字上快速重现问题:

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define BUFSIZE (100)

// Global variables

struct aiocb *cblist[2];

int theSocket;

void InitializeAiocbData(struct aiocb* pAiocb, char* pBuffer)

{

bzero( (char *)pAiocb, sizeof(struct aiocb) );

pAiocb->aio_fildes = theSocket;

pAiocb->aio_nbytes = BUFSIZE;

pAiocb->aio_offset = 0;

pAiocb->aio_buf = pBuffer;

}

void IssueReadOperation(struct aiocb* pAiocb, char* pBuffer)

{

InitializeAiocbData(pAiocb, pBuffer);

int ret = aio_read( pAiocb );

assert (ret >= 0);

}

void IssueWriteOperation(struct aiocb* pAiocb, char* pBuffer)

{

InitializeAiocbData(pAiocb, pBuffer);

int ret = aio_write( pAiocb );

assert (ret >= 0);

}

int main()

{

int ret;

int nPort = 11111;

char* szServer = "10.10.9.123";

// Connect to the remote server

theSocket = socket(AF_INET, SOCK_STREAM, 0);

assert (theSocket >= 0);

struct hostent *pServer;

struct sockaddr_in serv_addr;

pServer = gethostbyname(szServer);

bzero((char *) &serv_addr, sizeof(serv_addr));

serv_addr.sin_family = AF_INET;

serv_addr.sin_port = htons(nPort);

bcopy((char *)pServer->h_addr, (char *)&serv_addr.sin_addr.s_addr, pServer->h_length);

assert (connect(theSocket, (const sockaddr*)(&serv_addr), sizeof(serv_addr)) >= 0);

// Set the socket to be non-blocking

int oldFlags = fcntl(theSocket, F_GETFL) ;

int newFlags = oldFlags | O_NONBLOCK;

fcntl(theSocket, F_SETFL, newFlags);

printf("Socket flags: before=%o, after=%o\n", oldFlags, newFlags);

// Construct the AIO callbacks array

struct aiocb my_aiocb1, my_aiocb2;

char* pBuffer = new char[BUFSIZE+1];

bzero( (char *)cblist, sizeof(cblist) );

cblist[0] = &my_aiocb1;

cblist[1] = &my_aiocb2;

// Start the read and write operations on the same socket

IssueReadOperation(&my_aiocb1, pBuffer);

IssueWriteOperation(&my_aiocb2, pBuffer);

// Wait for I/O completion on both operations

int nRound = 1;

printf("\naio_suspend round #%d:\n", nRound++);

ret = aio_suspend( cblist, 2, NULL );

assert (ret == 0);

// Check the error status for the read and write operations

ret = aio_error(&my_aiocb1);

assert (ret == EWOULDBLOCK);

// Get the return code for the read

{

ssize_t retcode = aio_return(&my_aiocb1);

printf("First read operation results: aio_error=%d, aio_return=%d - That's the first EWOULDBLOCK\n", ret, retcode);

}

ret = aio_error(&my_aiocb2);

assert (ret == EINPROGRESS);

printf("Write operation is still \"in progress\"\n");

// Re-issue the read operation

IssueReadOperation(&my_aiocb1, pBuffer);

// Wait for I/O completion on both operations

printf("\naio_suspend round #%d:\n", nRound++);

ret = aio_suspend( cblist, 2, NULL );

assert (ret == 0);

// Check the error status for the read and write operations for the second time

ret = aio_error(&my_aiocb1);

assert (ret == EINPROGRESS);

printf("Second read operation request is suddenly marked as \"in progress\"\n");

ret = aio_error(&my_aiocb2);

assert (ret == 0);

// Get the return code for the write

{

ssize_t retcode = aio_return(&my_aiocb2);

printf("Write operation has completed with results: aio_error=%d, aio_return=%d\n", ret, retcode);

}

// Now try waiting for the read operation to complete - it'll just busy-wait, receiving "EWOULDBLOCK" indefinitely

do

{

printf("\naio_suspend round #%d:\n", nRound++);

ret = aio_suspend( cblist, 1, NULL );

assert (ret == 0);

// Check the error of the read operation and re-issue if needed

ret = aio_error(&my_aiocb1);

if (ret == EWOULDBLOCK)

{

IssueReadOperation(&my_aiocb1, pBuffer);

printf("EWOULDBLOCK again on the read operation!\n");

}

}

while (ret == EWOULDBLOCK);

}

提前致谢,

Yotam.

解决方法:

首先,O_NONBLOCK和AIO不混合.当相应的读或写不会被阻塞时,AIO将报告异步操作完成 – 并且使用O_NONBLOCK,它们永远不会阻塞,因此aio请求将始终立即完成(使用aio_return()给出EWOULDBLOCK).

其次,不要为两个同时发生的未完成的aio请求使用相同的缓冲区.在发出aio请求的时间和aio_error()告诉你已完成的时间之间,缓冲区应被视为完全禁止.

第三,AIO对同一文件描述符的请求排队,以便给出明智的结果.这意味着在读取完成之前不会发生写入 – 如果您需要先写入数据,则需要以相反的顺序发出AIO.以下工作正常,无需设置O_NONBLOCK:

struct aiocb my_aiocb1, my_aiocb2;

char pBuffer1[BUFSIZE+1], pBuffer2[BUFSIZE+1] = "Some test message";

const struct aiocb *cblist[2] = { &my_aiocb1, &my_aiocb2 };

// Start the read and write operations on the same socket

IssueWriteOperation(&my_aiocb2, pBuffer2);

IssueReadOperation(&my_aiocb1, pBuffer1);

// Wait for I/O completion on both operations

int nRound = 1;

int aio_status1, aio_status2;

do {

printf("\naio_suspend round #%d:\n", nRound++);

ret = aio_suspend( cblist, 2, NULL );

assert (ret == 0);

// Check the error status for the read and write operations

aio_status1 = aio_error(&my_aiocb1);

if (aio_status1 == EINPROGRESS)

puts("aio1 still in progress.");

else

puts("aio1 completed.");

aio_status2 = aio_error(&my_aiocb2);

if (aio_status2 == EINPROGRESS)

puts("aio2 still in progress.");

else

puts("aio2 completed.");

} while (aio_status1 == EINPROGRESS || aio_status2 == EINPROGRESS);

// Get the return code for the read

ssize_t retcode;

retcode = aio_return(&my_aiocb1);

printf("First operation results: aio_error=%d, aio_return=%d\n", aio_status1, retcode);

retcode = aio_return(&my_aiocb1);

printf("Second operation results: aio_error=%d, aio_return=%d\n", aio_status1, retcode);

或者,如果您不关心相互之间的读取和写入,您可以使用dup()为套接字创建两个文件描述符,并使用一个用于读取而另一个用于写入 – 每个都将具有AIO操作单独排队.

标签:linux,sockets,kernel,nonblocking,aio

来源: https://codeday.me/bug/20190630/1340573.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/306099.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

明源云·天际,地产⾏业的Salesforce Lightning Platform

源宝导读:2020年11月6日,明源云在CIO峰会上正式对外发布了“天际开放平台”,这是明源云凝聚其20多年行业经验打造的一款企业级PaaS平台。本文将介绍我们对企业级PaaS平台的行业思考,以及为加速泛地产生态链数字化转型而做的技术创…

c程序设计语言选修难吗,欢迎大家选修C语言程序设计这门课,本帖解释一下一些常见的问题...

置顶欢迎大家选修C语言程序设计这门课,本帖解释一下一些常见的问题叶卡林娜发表于2017年01月05日首先欢迎大家选修浙大翁恺老师的C语言程序设计课程。开课2天就看到讨论区已经有这么多帖子,说明同学们的学习热情很高。结合前几次开课的经验以及目前在讨论…

IdentityServer4系列 | 支持数据持久化

一、前言在前面的篇章介绍中,一些基础配置如API资源、客户端资源等数据以及使用过程中发放的令牌等操作数据,我们都是通过将操作数据和配置数据存储在内存中进行实现的,而在实际开发生产中,我们需要考虑如何处理数据持久化呢&…

c语言修仙受控可看吗,强推三本神奇到爆的小说,c语言修仙,程序员与修真会擦出什么火花...

大家好,我是小龙。今天我给大家推荐三本神奇到爆的小说,c语言修仙,程序员与修真会擦出什么火花!一《c语言修仙》【一十四洲】【简介】: 林浔是一个程序员,通宵编代码后发现自己身体内多了一个程序输入窗口。他尝试编了一个循环程序…

【Vue】Vue与ASP.NET Core WebAPI的集成

SPA单页面应用已经遍地开花,熟知的三大框架,Angular、Vue和React,其中Angular与React均可集成至ASP.NET Core,且提供了相关了中间件。但是Vue没有:“As far as I’m aware, we don’t have plans to introduce Vue-specific featu…

引入Jaeger——封装

随着微服务的普及,微服务间的调用全链路跟踪也火了起来,Jaeger(https://www.jaegertracing.io/)是CNCF孵化的全链路跟踪型项目,在.net core中,提供了一个Jaeger的Nuget(https://github.com/jaegertracing/jaeger-client-csharp)包…

c语言歌手预测成绩,5个裁判可以对10个歌手进行打分,计算各个歌手的最终得分排列...

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼if(flag0){printf("\n歌手信息为空,请利用键盘输入或文件读入!\n\n");printf("按任意键返回......");getchar(); getchar();}fpfopen("c:\\backup1.txt","w");for(…

BeetleX自定义http/websocket压测用例视频

虽然BeetleX扩展了tcp/websocket/webapi压测工具(工具下载可以访问https://github.com/beetlex-io/TCPBenchmarks),但测试工具都是针对消息定义来进行测试,很难整合完整的业务流程;如果能写代码那BeetleX组件提供一个测试组件可以更好地完成针…

临近年关,发生两起磁盘占满引发的服务下线故障

一口气说两个因为磁盘空间不足引发的应用故障。作为拿起键盘一把梭的Coder, 开发--->部署-->收工--->心旷神怡,滋一口82年的可乐.过了几个月,服务突然下线了!CTO又有杀程序员祭天的理由了!事故1:Azure App Se…

c语言幼儿园积木游戏,幼儿园《积木游戏》课件【三篇】

【导语】课件制作本身就是作者综合素养的一种体现,它显现出制作者对教育、教学、教材改革方向的把握,对课堂教学的理解,对现代教育技术的领悟。因此教师在设计课件时一定要吃透教学内容,设计出符合教学的方案用于课件。下面是无忧…

c语言 listview,C语言 SDK编程之通用控件的使用--ListView

一、ListView控件属于通用控件CONTROL中的一种,在SDK编程方式时要使用通用控件必须包含comctl32.dll,所以代码中要有头文件: commctrl.h 导入库:comctl32.lib在使用通用控件之前应该先调用InitCommonControls();初始化它以ListView控件为例…

蚂蚁调度AntJob-分布式任务调度系统

分布式任务调度系统,纯NET打造的重量级大数据实时计算平台,万亿级调度经验积累!面向中小企业大数据分析场景。开源地址:https://github.com/NewLifeX/AntJob使用教程:https://www.yuque.com/smartstone/blood/antjob体…

c语言怎么让图形界面单独显示,「分享」C语言如何编写图形界面

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼贴吧内经常有人问C语言是不是只能用于字符终端界面开发,不能用于图形界面。大家也都有回答,需要其他的库。MFC,GTK,QT。本人近期刚用GTK库加上纯C写成了第一个LINUX实用程序。现在与大…

如何在 ASP.NET Core 中 自定义中间件

ASP.NET Core 是一个跨平台,开源的,轻量级,高性能 并且高度模块化的web框架,同时扩展性也是非常强,你可以在 request -> response 请求管道中安插各种中间件来根据自己的场景定制化,比如说:监…

c语言电报关系的题目,c语言所有题目以跟答案.doc

c语言所有题目以跟答案判断题关系运算符<与的优先级相同。 N2.7&312的值是15. N3.在TurboC中&#xff0c;整型数据在内存中占2个字节。 YC语言本身不提供输入输出语句&#xff0c;输入输出操作是由函数实现的。 Y5.char [ ]“Very good”:是一个合法的为字符串数组赋值的…

ASP.NET Core Authentication and Authorization

最近把一个Asp .net core 2.0的项目迁移到Asp .net core 3.1&#xff0c;项目启动的时候直接报错:InvalidOperationException: Endpoint CoreAuthorization.Controllers.HomeController.Index (CoreAuthorization) contains authorization metadata, but a middleware was not …

android dialog 自定义布局,如何设置AlertDialog的自定义布局?

调用我的对话框:alertDialog showInfoDialog(message "$wrongPasscodeMessage\n$retryMessage")方法如下:fun FragmentActivity.showInfoDialog(message: String?): AlertDialog? {return try {val customLayout layoutInflater.inflate(R.layout.custom_layout…

ASP.NET Core 依赖注入-集成 Autofac

概述ASP.NET Core 支持依赖关系注入 (DI) 软件设计模式&#xff0c;这是一种在类及其依赖关系之间实现控制反转 (IoC) 的技术。默认服务容器是 Microsoft.Extensions.DependencyInjection 。内置的服务容器一般能满足简单的框架和部分消费者应用的需求。 建议使用内置容器&…

android 打开谷歌导航,国内开启google位置记录功能/android版google maps 7+上,恢复位置记录功能在国内使用(需root)...

android版google 地图在 7以后的版本上&#xff0c;位置记录功能在国内不能用了&#xff0c;提示本功能不能在中国使用。至少对本人&#xff0c;“位置记录”功能是非常有用的功能&#xff0c;尤其是骑车出行时记录自己的路线。目前还没找到替代产品。之前一段时间内恢复回旧版…

程序员过关斩将--少年派登录安全的奇幻遐想

“据说&#xff0c;这篇也是快餐&#xff0c;完全符合年轻人口味说到登录&#xff0c;无人不知无人不晓。每一个有用户体系的相关系统都会有登录的入口&#xff0c;登录是为了确认操作人的正确性。说到登录安全&#xff0c;其实是一个很伟大的命题&#xff0c;不过常用的手段也…