亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C > 正文

使用udp發送>=128K的消息會報ENOBUFS的錯誤的解決方法

2020-01-26 13:27:39
字體:
來源:轉載
供稿:網友

這是一個困擾我兩天的問題,

Google和Baidu沒有找到解決方法!

此文為記錄這個問題,并給出原因和解決方法。

1、Unix domain socket簡介

unix域協議并不是一個實際的協議族,而是在單個主機上執行客戶/服務器通信的一種方法,所用API于在不同主機上執行客戶/服務器通信所有的API(套接字API,如AF_INET、AF_INET6等類型的API)相同。unix域協議可以視為是進程之間本地通信IPC的一種。

unix域提供兩類套接口:字節流套接口(類似TCP)和數據報套接口(類似UDP)。使用Unix域套接口的理由有三:

Unix域套接口往往比位于同一主機的TCP套接口快出一倍。Unix域套接口可用于在同一主機上的不同進程之間傳遞描述字。Unix域套接口把客戶的憑證(用戶ID和用戶組ID)提供給服務器,從而實現能夠提供額外的安全檢查措施。

Unix域中用域標識客戶和服務器的協議地址是普通文件系統中的路徑名(類比:IPv4協議的地址由一個32位地址和一個16位端口號構成,IPv6協議的地址由一個128位地址和16位端口號構成。)。

2、問題描述

簡單介紹了Unix域套接口之后,進入主題――描述我碰到的問題。由于unix域套接口用于本機間進程通信比網絡套接口效率高,因為它是不經過協議棧的!在項目中選擇了unix域的數據報套接口。在使用過程中碰到了如下,問題:發送<128K的消息時,客戶、進程可以正常收發消息;發送>=128K的消息時,發送端(sendto)返回ENOBUFS的錯誤。

服務器的代碼如下:

服務器端

#include<stdio.h>#include<stdlib.h>#include<sys/types.h>#include<sys/socket.h>#include<sys/un.h>#include<errno.h>//define send and recv buf size#define BUFSIZE 512*1024//define unix domain socket path#define pmmanager "/tmp/pmmanager"#define pmapi "/tmp/pmapi"int main(int argc, char** argv){char rx_buf[BUFSIZE];int pmmanager_fd, ret;socklen_t len;struct sockaddr_un pmmanager_addr, pmapi_addr;//create pmmanager socket fdpmmanager_fd = socket(AF_UNIX, SOCK_DGRAM, 0);if(pmmanager_fd == -1){perror("cannot create pmmanager fd.");}unlink(pmmanager);memset(&pmmanager_addr, 0, sizeof(pmmanager_addr));pmmanager_addr.sun_family = AF_UNIX;strncpy(pmmanager_addr.sun_path, pmmanager, sizeof(pmmanager_addr.sun_path)-1);//bind pmmanager_fd to pmmanager_addrret = bind(pmmanager_fd, (struct sockaddr*)&pmmanager_addr, sizeof(pmmanager_addr));if(ret == -1){perror("can not bind pmmanager_addr");}int recvBufSize;len = sizeof(recvBufSize);ret = getsockopt(pmmanager_fd, SOL_SOCKET, SO_RCVBUF, &recvBufSize, &len);if(ret ==-1){perror("getsocket error.");}printf("Before setsockopt, SO_RCVBUF-%d/n",recvBufSize); recvBufSize = 512*1024;ret = setsockopt(pmmanager_fd, SOL_SOCKET, SO_RCVBUF, &recvBufSize, len);if(ret == -1){perror("setsockopt error.");}ret = getsockopt(pmmanager_fd, SOL_SOCKET, SO_RCVBUF, &recvBufSize, &len);if(ret ==-1){perror("getsocket error.");}printf("Set recv buf successful, SO_RCVBUF-%d/n",recvBufSize); int recvSize;memset(&pmapi_addr, 0, sizeof(pmapi_addr));len = sizeof(pmapi_addr);printf("==============wait for msg from pmapi====================/n");for(;;){memset(rx_buf, 0, sizeof(rx_buf));recvSize = recvfrom(pmmanager_fd, rx_buf, sizeof(rx_buf), 0, (struct sockaddr*)&pmapi_addr, &len);if(recvSize == -1){perror("recvfrom error.");}printf("Recved message from pmapi: %s/n", rx_buf);}}

客戶端的代碼如下:

客戶端

#include<stdio.h>#include<stdlib.h>#include<sys/types.h>#include<sys/socket.h>#include<sys/un.h>#include<errno.h>//define send and recv buf size#define BUFSIZE 250*1024//define unix domain socket path#define pmmanager "/tmp/pmmanager"#define pmapi "/tmp/pmapi"int main(int argc, char** argv){char tx_buf[BUFSIZE];int pmapi_fd, ret;socklen_t len;struct sockaddr_un pmmanager_addr, pmapi_addr;//create pmmanager socket fdpmapi_fd = socket(AF_UNIX, SOCK_DGRAM, 0);if(pmapi_fd == -1){perror("cannot create pmapi fd.");}unlink(pmapi);//configure pmapi's addrmemset(&pmapi_addr, 0, sizeof(pmapi_addr));pmapi_addr.sun_family = AF_UNIX;strncpy(pmapi_addr.sun_path, pmapi, sizeof(pmapi_addr.sun_path)-1);//bind pmapi_fd to pmapi_addrret = bind(pmapi_fd, (struct sockaddr*)&pmapi_addr, sizeof(pmapi_addr));if(ret == -1){perror("bind error.");}int sendBufSize;len = sizeof(sendBufSize);ret = getsockopt(pmapi_fd, SOL_SOCKET, SO_SNDBUF, &sendBufSize, &len);if(ret ==-1){perror("getsocket error.");}printf("Before setsockopt, SO_SNDBUF-%d/n",sendBufSize); sendBufSize = 512*1024;ret = setsockopt(pmapi_fd, SOL_SOCKET, SO_SNDBUF, &sendBufSize, len);if(ret == -1){perror("setsockopt error.");}ret = getsockopt(pmapi_fd, SOL_SOCKET, SO_SNDBUF, &sendBufSize, &len);if(ret ==-1){perror("getsocket error.");}printf("Set send buf successful, SO_SNDBUF-%d/n/n/n", sendBufSize); //configure pmmanager's addrmemset(&pmmanager_addr, 0, sizeof(pmmanager_addr));pmmanager_addr.sun_family = AF_UNIX;strncpy(pmmanager_addr.sun_path, pmmanager, sizeof(pmmanager_addr)-1);len = sizeof(pmmanager_addr);int sendSize = 0;int i;for(i=1; i<=4; i++){memset(tx_buf, '0', sizeof(tx_buf));sprintf(tx_buf, "send msg %d to pmmanager.", i);printf("%s, msg size - %d/n",tx_buf, sizeof(tx_buf));sendSize = sendto(pmapi_fd, tx_buf, sizeof(tx_buf), 0, (struct sockaddr*)&pmmanager_addr, len);if(sendSize == -1){perror("sendto error.");}printf("Send message to pmmanager: %s/n/n/n", tx_buf);}}

3、可能碰到的另外一個問題

如果你沒有設置足夠大的發送緩沖區大小,你很有可能碰到EMSGSIZE的錯誤!因為應用程序寫了一個大于套機口發送緩沖區大小的數據報,內核報EMSGSIZE錯誤。如下圖:

(注意:UDP套接口有發送緩沖區的大小,并且可以通過SO_SNDBUF套接口選項修改。不過它僅僅是寫到套接口的UDP數據報的大小,因為UDP是不可靠的,它不必保存應用進程的數據拷貝,因此無需一個真正的發送緩沖區。)上面的代碼已經設置了足夠大的發送緩沖區大小。

4、我的嘗試

在sendto發送>=128K大小的消息時,返回ENOBUFS錯誤。

我懷疑是否是sendto()的原因,我改用sendmsg(),未果還是返回這個錯誤。有人說是:“發送消息太頻繁,間隔太短”。其實項目中發送消息根本就不頻繁,背著死馬當活馬醫,未果還是返回這個錯誤。嘗試修改/proc/sys/net/core下面的各種相關選項,如

未果,還是返回這個錯誤。(其它路徑下的相關選項也試了,不行)?我無從下手了,不知道128K的這個限制在哪?既然“No buffer space available”,我怎樣給他空間?5、最終原因及解決辦法(都是內核惹得禍?。。┲链?,我實在沒有辦法了,不知道如何解決!但是從錯誤ENOBUFS的說明:

ENOBUFS means there is no sufficient memory available and the system(kernel) can not allocate any more.Application will usually retry the operation when it detects this error from asystem call since it indicates there is a transient resource shortage.It is the Operating system that refuses the resource request from the listener.The virtual memory allocation routine of the OS will determine if a swap can bemade to disk of a real memory segment thereby allowing the listener access tosome more real memory.

可以看出一些端倪,這肯定跟內存分配有關!而且限制在分配128K就失?。±肧ocket進行進程間的通信,需要經過Linux內核:進程1將數據寫到內核,進程2從內核讀取數據。內核必須申請一個空間來存放數據包!實際上,socket發送數據包時,需要從slab中申請一塊cache存放數據包。在2.6.21內核中(這就是我們公司服務器的內核版本),slab分配器最大支持的size為128K(詳情可見/proc/slabinfo)。在2.6.31內核中,slab分配器最大支持的size大小為32M。所以2.6.21內核上,發送大于128K的數據包時,Kmalloc()會失敗,并返回no buffer的錯誤。建議:對于本地進程通信,可以使用其它的IPC方式,進行數據通信,如shm、pipe等。找出了原因,可以采用以下方式來解決該問題:升級內核,或修改內核的這個限制。改用unix 域udp套接口為unix域tcp套接口(最終我們采用的方式)。改用其它的IPC方式(這個涉及到太多的修改,故我們放棄使用)。附/proc/slabinfo 信息:size-131072即128K的限制!

代碼

size-131072(DMA) 0 0 131072 1 32 : tunables 8 4 0 : slabdata 0 0 0
size-131072 0 0 131072 1 32 : tunables 8 4 0 : slabdata 0 0 0
size-65536(DMA) 0 0 65536 1 16 : tunables 8 4 0 : slabdata 0 0 0
size-65536 0 0 65536 1 16 : tunables 8 4 0 : slabdata 0 0 0
size-32768(DMA) 0 0 32768 1 8 : tunables 8 4 0 : slabdata 0 0 0
size-32768 0 0 32768 1 8 : tunables 8 4 0 : slabdata 0 0 0
size-16384(DMA) 0 0 16384 1 4 : tunables 8 4 0 : slabdata 0 0 0
size-16384 0 0 16384 1 4 : tunables 8 4 0 : slabdata 0 0 0
size-8192(DMA) 0 0 8192 1 2 : tunables 8 4 0 : slabdata 0 0 0
size-8192 0 0 8192 1 2 : tunables 8 4 0 : slabdata 0 0 0
size-4096(DMA) 0 0 4096 1 1 : tunables 24 12 0 : slabdata 0 0 0
size-4096 4 4 4096 1 1 : tunables 24 12 0 : slabdata 4 4 0
size-2048(DMA) 0 0 2048 2 1 : tunables 24 12 0 : slabdata 0 0 0
size-2048 12 14 2048 2 1 : tunables 24 12 0 : slabdata 7 7 0
size-1024(DMA) 0 0 1024 4 1 : tunables 54 27 0 : slabdata 0 0 0
size-1024 11 12 1024 4 1 : tunables 54 27 0 : slabdata 3 3 0
size-512(DMA) 0 0 512 8 1 : tunables 54 27 0 : slabdata 0 0 0
size-512 208 208 512 8 1 : tunables 54 27 0 : slabdata 26 26 0
size-256(DMA) 0 0 256 15 1 : tunables 120 60 0 : slabdata 0 0 0
size-256 75 75 256 15 1 : tunables 120 60 0 : slabdata 5 5 0
size-192(DMA) 0 0 192 20 1 : tunables 120 60 0 : slabdata 0 0 0
size-192 40 40 192 20 1 : tunables 120 60 0 : slabdata 2 2 0
size-128(DMA) 0 0 128 30 1 : tunables 120 60 0 : slabdata 0 0 0
size-128 86 90 128 30 1 : tunables 120 60 0 : slabdata 3 3 0
size-96(DMA) 0 0 96 40 1 : tunables 120 60 0 : slabdata 0 0 0
size-96 388 400 96 40 1 : tunables 120 60 0 : slabdata 10 10 0
size-64(DMA) 0 0 64 59 1 : tunables 120 60 0 : slabdata 0 0 0
size-32(DMA) 0 0 32 113 1 : tunables 120 60 0 : slabdata 0 0 0
size-64 451 472 64 59 1 : tunables 120 60 0 : slabdata 8 8 0
size-32 871 904 32 113 1 : tunables 120 60 0 : slabdata 8 8 0

我在Ubuntu 10.10上測試,不會報ENOBUFS的錯誤。內核版本為:

/proc/slabinfo的信息如下,跟上面的有些差異:

kmalloc的最大限制是8192K,故我們運行上述程序沒有問題!原來都是內核惹得禍阿,害我困惑那么久?。。aidu和google都沒有找到原因,因此分享此文,以警惕后者。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美激情免费视频| 亚洲国产精品嫩草影院久久| 性色av一区二区三区在线观看| 欧美日韩激情网| 久久天天躁夜夜躁狠狠躁2022| 欧美性jizz18性欧美| 亚洲激情自拍图| 日韩精品免费电影| 欧美国产在线电影| 日韩精品在线观| 日韩有码片在线观看| 日本一本a高清免费不卡| 精品久久久久久电影| 成人免费在线视频网站| 日韩久久免费视频| 国产精品高潮视频| 国产网站欧美日韩免费精品在线观看| 亚洲精品国产精品久久清纯直播| 亚洲欧美在线免费观看| 欧美最顶级的aⅴ艳星| 欧洲s码亚洲m码精品一区| 亚洲视频精品在线| 久久精品视频在线观看| 国产精品三级久久久久久电影| 亚洲人成亚洲人成在线观看| 亚洲国产成人爱av在线播放| 午夜精品一区二区三区在线| 亚洲精品久久久久中文字幕欢迎你| 国产精品高潮呻吟久久av无限| 欧美精品少妇videofree| 国产成人精品网站| 韩曰欧美视频免费观看| 亚洲精品色婷婷福利天堂| 亚洲免费视频一区二区| 国产成+人+综合+亚洲欧美丁香花| 亚洲女人天堂成人av在线| 欧美巨大黑人极品精男| 国产日韩欧美中文在线播放| 亚洲国产精品电影在线观看| 日本精品视频在线| 久久精品国产免费观看| 成人免费大片黄在线播放| 欧美人与性动交| 久久亚洲综合国产精品99麻豆精品福利| 国产精品久久久久久亚洲调教| 一区二区欧美亚洲| 久久久久中文字幕2018| 国产精品入口日韩视频大尺度| 奇米四色中文综合久久| 精品国产91久久久久久老师| 国产精品大陆在线观看| 国产一区二区三区视频在线观看| 欧美亚洲视频一区二区| 久久精品国产精品亚洲| 成人美女av在线直播| 91天堂在线观看| 大胆欧美人体视频| 久久久免费精品视频| 日韩黄在线观看| 97欧美精品一区二区三区| 欧美日韩国产综合视频在线观看中文| 国产999在线观看| 97久久精品人人澡人人爽缅北| 国产成人综合精品在线| 国产精品免费在线免费| 国产亚洲a∨片在线观看| 久久亚洲精品成人| 97精品在线观看| 91久久精品国产| 亚洲人午夜精品| 国内精品中文字幕| 欧美成人亚洲成人日韩成人| 岛国av一区二区在线在线观看| 在线观看精品国产视频| 夜夜嗨av一区二区三区四区| 欧美午夜片在线免费观看| 亚洲成色999久久网站| 欧美诱惑福利视频| 国产91精品久久久久久| 国产精品视频在线观看| 日本在线观看天堂男亚洲| 国产91免费看片| 一区二区福利视频| 欧美一级淫片videoshd| 一本色道久久88综合日韩精品| 亚洲裸体xxxx| 亚州精品天堂中文字幕| 国产精品xxx视频| 国产精品久久久久久久久久99| 亚洲一品av免费观看| 久久久久久91香蕉国产| 日韩一区av在线| 亚洲成人黄色网| 亚洲欧美国产精品专区久久| 一区二区三区四区在线观看视频| 色伦专区97中文字幕| 久久久亚洲欧洲日产国码aⅴ| 欧美一区二区三区免费观看| 欧美一性一乱一交一视频| 欧美一区二区.| 国产精品久久久久久久久影视| 日韩精品在线私人| 91av视频在线观看| 欧美午夜精品久久久久久久| 国产精品夜间视频香蕉| 精品视频在线观看日韩| 96精品久久久久中文字幕| 国产玖玖精品视频| 一区二区亚洲精品国产| 日韩在线欧美在线国产在线| 亚洲成人激情在线| 精品日本高清在线播放| 久久精品视频一| 正在播放欧美一区| 国产成人精品久久二区二区| 国产成人极品视频| 日韩在线国产精品| 欧美色播在线播放| 国产精品一区二区3区| 成人免费xxxxx在线观看| 日韩高清av在线| 欧美日韩国产色视频| 伦理中文字幕亚洲| 亚洲天堂男人天堂女人天堂| 日韩在线免费高清视频| 国产午夜精品一区理论片飘花| 美女999久久久精品视频| 亚洲va久久久噜噜噜| 精品精品国产国产自在线| 亚洲精品国产suv| 欧美性猛交xxxx黑人| 国产精品成久久久久三级| 欧美日韩中文字幕在线视频| 日韩精品视频在线免费观看| 日韩精品极品在线观看播放免费视频| 日韩电影免费在线观看| 中文字幕精品一区久久久久| 久久影院中文字幕| 欧美性生活大片免费观看网址| 亚洲图片制服诱惑| 久久久久久91| 亚洲理论片在线观看| 法国裸体一区二区| 亚洲a级在线观看| 国产精品久久久久久久久久ktv| 亚洲国产女人aaa毛片在线| 91精品啪在线观看麻豆免费| 日韩欧美高清在线视频| 91tv亚洲精品香蕉国产一区7ujn| 欧美性一区二区三区| 中文在线不卡视频| 成人欧美一区二区三区在线湿哒哒| 一区二区av在线| 国产亚洲人成网站在线观看| 亚洲精品美女网站| 亚洲精品美女久久| 久久久久久噜噜噜久久久精品| 欧美老肥婆性猛交视频| 国产精品高清在线观看| 日韩视频欧美视频| 欧美中文在线观看国产| 日本一欧美一欧美一亚洲视频| 国产精品久久一区主播| 中文字幕亚洲无线码在线一区|