清空socket接收佇列

2021-05-08 22:09:09 字數 1616 閱讀 3783

在socket建立時,linux的核心會為socket分配乙個傳送緩衝區和乙個接收緩衝區,實際上是乙個struct sk_buff的佇列,當我們呼叫send/sendto/sendmsg及recv/recvfrom/recvmsg時,會傳送或接收佇列中的第乙個資料。

現在我們只考慮接收的情況,如果甲一直不停的向乙傳送訊息,而乙中每次呼叫recv/recvfrom/recvmsg都想得到最新的資料,怎麼辦?

這就需要我們對linux的緩衝區進行清空。而緩衝區是在核心中的,不允許直接操作。還好,有兩個函式可以解決這個問題。

第乙個是int setsockopt(int socket, int level, int option_name, const void *option_value, socklen_t option_len), 他是對

socket的設定。我們可以通過它修改接收緩衝區的大小。他還有很多功能,見man setsockopt.

int llen, lret

lret = setsockopt(sock, sol_socket, so_rcvbuf, &llen, sizeof(int));

sock就是我們建立的socket 的描述符。

如果對linux核心**進行研究,會發現llen不是設定成所有的值都有效。

if (val > sysctl_rmem_max)

val = sysctl_rmem_max;

set_rcvbuf:

sk->sk_userlocks |= sock_rcvbuf_lock;

/* fixme: is this lower bound the right one? */

if ((val * 2) < sock_min_rcvbuf)

sk->sk_rcvbuf = sock_min_rcvbuf;

else

sk->sk_rcvbuf = val * 2;

break;

也就說,他有乙個最大值和乙個最小值。 最大值是262144, 最小值是256。

我們在看一下核心中緩衝區分配的函式

...size = skb_data_align(size);

...skb->truesize = size + sizeof(struct sk_buff);

在sock_queue_rcv_skb函式中有

if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=

(unsigned)sk->sk_rcvbuf)

這樣,當接收到乙個資料報後,核心緩衝區會分配size + sizeof(struct sk_buff)大小的緩衝區,其中size是cache line對齊的。

也就是說,只有我們設定的緩衝區大於這個值,資料才會到使用者空間。

好了,我們設定了接收區的大小以後,緩衝區中只有乙個資料報,可以用select函式進行清空。

struct timeval stwait;

fd_set         stfdset;

int            lret;

stwait.tv_sec = 0;

stwait.tv_usec = 0;

while(1)

然後再呼叫recvfrom接收最新的訊息。

Linux下如何清空socket的接收緩衝區的資料

最近碰到乙個問題,對於阻塞模式的socket通訊,如果要實現裝置的命令控制,那麼進入命令流前,緩衝區不能存有上次通訊沒有取回的資訊,否則一旦命令發出,然後讀取緩衝區,很顯然會讀到上一次的剩餘資料。做法當然很簡單,就是先清除接收區的緩衝資料,可是如何清除?網上有很多這樣的問題,但都沒什麼規範的解決辦法...

socket接收訊息

標頭檔案在主頁 編譯方式 gcc server.c o server執行方式 server 埠號程式主體 int main int argc,char ar server 埠 建立udp套接字 fd socket af inet,sock dgram,0 準備跟af inet 即ipv4網路層協議 ...

celery清空佇列

本人在使用python celery佇列時,有時候需要清空佇列,但是python celery似乎並沒有清空佇列的api 至少我沒找到 所以使用redis cli工具進行佇列清空 使用redis cli工具,命令如下,在終端直接輸入 redis cli n 15 ltrim transcode 0 ...