Linux - send 出现 Resource temporarily unavailable
1.前言
主機(jī)和AI設(shè)備通訊時候,通過send發(fā)送小數(shù)據(jù),發(fā)送和接受都正常。可是發(fā)送YUV數(shù)據(jù)時候,一幀720P數(shù)據(jù)大概1.3M左右,發(fā)送時候就會報錯Resource temporarily unavailable錯誤,只發(fā)送了一幀的部分?jǐn)?shù)據(jù),導(dǎo)致該幀數(shù)據(jù)不完整,無法使用。通過錯誤碼查找,是由于發(fā)送緩存池滿導(dǎo)致的。
2.代碼
int Send(int handle, unsigned char *buf, int len,int flags, const int selectSec, const int selectUsec) {int sendtotal = -1;int sendlen = 0;fd_set wset;struct timeval tv;FD_ZERO(&wset);FD_SET(handle, &wset);tv.tv_sec = selectSec / 1000000;tv.tv_usec = selectUsec % 1000000;int result = select(handle + 1, NULL, &wset, NULL, &tv);if ( result > 0){if (FD_ISSET(handle, &wset)){sendtotal = 0;while(sendtotal < len){sendlen = send(handle, (buf + sendtotal), (len - sendtotal) , flags);if(sendlen <= 0){perror("-----[send]----:");return -1;}sendtotal += sendlen;}}}else{perror("-----[select]----:");}return sendtotal; }?
3.解決方法
? ? ? 在阻塞模式下,send函數(shù)的過程是將應(yīng)用程序請求發(fā)送的數(shù)據(jù)拷貝到發(fā)送緩存中發(fā)送并得到確認(rèn)后再返回.但由于發(fā)送緩存的存在,表現(xiàn)為:如果發(fā)送緩存大小比請求發(fā)送的大小要大,那么send函數(shù)立即返回,同時向網(wǎng)絡(luò)中發(fā)送數(shù)據(jù);否則,send向網(wǎng)絡(luò)發(fā)送緩存中不能容納的那部分?jǐn)?shù)據(jù),并等待對端確認(rèn)后再返回(接收端只要將數(shù)據(jù)收到接收緩存中,就會確認(rèn),并不一定要等待應(yīng)用程序調(diào)用recv);
??????在非阻塞模式下,send函數(shù)的過程僅僅是將數(shù)據(jù)拷貝到協(xié)議棧的緩存區(qū)而已,如果緩存區(qū)可用空間不夠,則盡能力的拷貝,返回成功拷貝的大小;如緩存區(qū)可用空間為0,則返回-1,同時設(shè)置errno為EAGAIN.
? ? ?當(dāng)客戶通過Socket提供的send函數(shù)發(fā)送大的數(shù)據(jù)包時,就可能返回一個EGGAIN的錯誤。該錯誤產(chǎn)生的原因是由于send函數(shù)中的size變量大小超過了tcp_sendspace的值。tcp_sendspace定義了應(yīng)用在調(diào)用send之前能夠在kernel中緩存的數(shù)據(jù)量。當(dāng)應(yīng)用程序在socket中設(shè)置了O_NDELAY或者O_NONBLOCK屬性后,如果發(fā)送緩存被占滿,send就會返回EAGAIN的錯誤。
解決方法:
? ? ?1)在調(diào)用send前,在setsockopt函數(shù)中為SNDBUF設(shè)置更大的值
? ? ? ? ?intopt=SO_REUSEADDR;
? ? ? ? setsockopt(tcp_client_sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
??????????opt = 512*1024;
??????????int optlen = sizeof(int);
??????????setsockopt(tcp_client_sock,SOL_SOCKET,SO_SNDBUF,&opt,sizeof(int));
??????????getsockopt(tcp_client_sock,SOL_SOCKET,SO_SNDBUF,&opt,&optlen);?
2).使用write替代send,因為write沒有設(shè)置O_NDELAY或者O_NONBLOCK
代碼如下:
采用write并分包發(fā)送策略?
int Send_YUV_Slice_Packet(int socket, unsigned char *data, unsigned int len) {/**分包策略省略*/{while (hasSndLen<packetlen){nRet = write(socket, sendBuf+hasSndLen, needSndLen);if (nRet <= 0){int errNo = errno;if ((nRet < 0) && ((errNo == EINTR) || (errNo == EAGAIN))){usleep(10*1000);/**發(fā)送區(qū)為滿時候循環(huán)等待,直到可寫為止*/continue;}else{printf("write Err, nRet=%d, errno=%d \n", nRet, errNo);return -1;}}else{hasSndLen += nRet;if (hasSndLen < packetlen){needSndLen = packetlen - hasSndLen;usleep(10*1000);}}} }return 0;}?
總結(jié)
以上是生活随笔為你收集整理的Linux - send 出现 Resource temporarily unavailable的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: flink作业提交流程
- 下一篇: Environment 注入servic