Linux - send 出现 Resource temporarily unavailable
1.前言
主機和AI設備通訊時候,通過send發送小數據,發送和接受都正常??墒前l送YUV數據時候,一幀720P數據大概1.3M左右,發送時候就會報錯Resource temporarily unavailable錯誤,只發送了一幀的部分數據,導致該幀數據不完整,無法使用。通過錯誤碼查找,是由于發送緩存池滿導致的。
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函數的過程是將應用程序請求發送的數據拷貝到發送緩存中發送并得到確認后再返回.但由于發送緩存的存在,表現為:如果發送緩存大小比請求發送的大小要大,那么send函數立即返回,同時向網絡中發送數據;否則,send向網絡發送緩存中不能容納的那部分數據,并等待對端確認后再返回(接收端只要將數據收到接收緩存中,就會確認,并不一定要等待應用程序調用recv);
??????在非阻塞模式下,send函數的過程僅僅是將數據拷貝到協議棧的緩存區而已,如果緩存區可用空間不夠,則盡能力的拷貝,返回成功拷貝的大小;如緩存區可用空間為0,則返回-1,同時設置errno為EAGAIN.
? ? ?當客戶通過Socket提供的send函數發送大的數據包時,就可能返回一個EGGAIN的錯誤。該錯誤產生的原因是由于send函數中的size變量大小超過了tcp_sendspace的值。tcp_sendspace定義了應用在調用send之前能夠在kernel中緩存的數據量。當應用程序在socket中設置了O_NDELAY或者O_NONBLOCK屬性后,如果發送緩存被占滿,send就會返回EAGAIN的錯誤。
解決方法:
? ? ?1)在調用send前,在setsockopt函數中為SNDBUF設置更大的值
? ? ? ? ?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沒有設置O_NDELAY或者O_NONBLOCK
代碼如下:
采用write并分包發送策略?
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);/**發送區為滿時候循環等待,直到可寫為止*/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;}?
總結
以上是生活随笔為你收集整理的Linux - send 出现 Resource temporarily unavailable的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: flink作业提交流程
- 下一篇: 命令行测速工具 linux,Linux命