1. 程式人生 > >Linux UDP socket 設定為的非阻塞模式與阻塞模式區別

Linux UDP socket 設定為的非阻塞模式與阻塞模式區別


UDP socket 設定為的非阻塞模式 

?
1 Len = recvfrom(SocketFD, szRecvBuf, sizeof(szRecvBuf), MSG_DONTWAIT, (struct sockaddr *)&SockAddr,&ScokAddrLen);

UDP socket 設定為的阻塞模式 

?
1 Len = recvfrom(SocketFD, szRecvBuf, sizeof(szRecvBuf), 0, (struct sockaddr *)&SockAddr,&ScokAddrLen);

Linux socket程式設計之阻塞套接字和非阻塞套接字

  每一個TCP套介面有一個傳送緩衝區,可以用SO_SNDBUF套介面選項來改變這個緩衝區的大小。當應用程序呼叫 write時,核心從應用程序的緩衝區中拷貝所有資料到套介面的傳送緩衝區。如果套介面的傳送緩衝區容不下應用程式的所有資料(或是應用程序的緩衝區大於套介面傳送緩衝區,或是套介面傳送緩衝區還有其他資料),應用程序將被掛起(睡眠)。這裡假設套介面是阻塞的,這是通常的預設設定。核心將不從write系統呼叫返回,直到應用程序緩衝區中的所有資料都拷貝到套介面傳送緩衝區。因此從寫一個TCP套介面的write呼叫成功返回僅僅表示我們可以重新使用應用程序的緩衝區。它並不告訴我們對端的 TCP或應用程序已經接收了資料。 

    TCP取套介面傳送緩衝區的資料並把它傳送給對端TCP,其過程基於TCP資料傳輸的所有規則。對端TCP必須確認收到的資料,只有收到對端的ACK,本端TCP才能刪除套介面傳送緩衝區中已經確認的資料。TCP必須保留資料拷貝直到對端確認為止。

1 輸入操作: read、readv、recv、recvfrom、recvmsg

    如果某個程序對一個阻塞的TCP套介面呼叫這些輸入函式之一,而且該套介面的接收緩衝區中沒有資料可讀,該程序將被投入睡眠,直到到達一些資料。既然 TCP是位元組流協議,該程序的喚醒就是隻要到達一些資料:這些資料既可能是單個位元組,也可以是一個完整的TCP分節中的資料。如果想等到某個固定數目的資料可讀為止,可以呼叫readn函式,或者指定MSG_WAITALL標誌。

    既然UDP是資料報協議,如果一個阻塞的UDP套介面的接收緩衝區為空,對它呼叫輸入函式的程序將被投入睡眠,直到到達一個UDP資料報。

    對於非阻塞的套介面,如果輸入操作不能被滿足(對於TCP套介面即至少有一個位元組的資料可讀,對於UDP套介面即有一個完整的資料報可讀),相應呼叫將立即返回一個EWOULDBLOCK錯誤。

2 輸出操作:write、writev、send、sendto、sendmsg

    對於一個TCP套介面,核心將從應用程序的緩衝區到該套介面的傳送緩衝區拷貝資料。對於阻塞的套介面,如果其傳送緩衝區中沒有空間,程序將被投入睡眠,直到有空間為止。

    對於一個非阻塞的TCP套介面,如果其傳送緩衝區中根本沒有空間,輸出函式呼叫將立即返回一個EWOULDBLOCK錯誤。如果其傳送緩衝區中有一些空間,返回值將是核心能夠拷貝到該緩衝區中的位元組數。這個位元組數也稱為不足計數(short count)

    UDP套介面沒有真正的傳送緩衝區。核心只是拷貝應用程序資料並把它沿協議棧向下傳送,漸次冠以UDP頭部和IP頭部。因此對一個阻塞的UDP套介面,輸出函式呼叫將不會因為與TCP套介面一樣的原因而阻塞,不過有可能會因其他的原因而阻塞。