#include <sys/types.h> #include <sys/socket.h> ssize_t recv(int sockfd, void *buf, size_t len, int flags); ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
recv(),recvfrom()調用被用於從套接字接收消息。 它們可用於在無連接和面向連接的套接字上接收數據。正如,recv()和read()之間的唯一區別是標志的存在,使用零標志參數時,recv()通常等效於read()。同理,recv(sockfd,buf,len,flags)等價於recvfrom(sockfd,buf,len,flags,NULL,NULL)。
成功完成后,這兩個調用都將返回消息的長度。 如果消息太長而無法容納在提供的緩沖區中,則多余的字節可能會被丟棄,此時,返回值則取決於接收消息的套接字類型。
如果套接字上沒有可用的消息,則接收調用將等待消息到達,除非套接字是非阻塞的,在這種情況下,將返回值-1且外部變量errno設置為EAGAIN 或EWOULDBLOCK。 接收呼叫通常返回任何可用數據,最多至請求的數量,而不是等待收到請求的全部數量。
flags參數
flags參數是通過對以下一個或多個值進行“或”運算形成。
MSG_CMSG_CLOEXEC 僅僅recvmsg()函數使用。
MSG_DONTWAIT 啟用非阻塞操作。 這提供與設置O_NONBLOCK標志類似的行為(通過fcntl(2)F_SETFL操作),但不同之處在於MSG_DONTWAIT是每個通話選項,而O_NONBLOCK是設置打開文件描述,這將影響在調用進程中的所有線程以及保存了同一文件描述符的其他進程。
MSG_ERRQUEUE This flag specifies that queued errors should be received from the socket error queue.
MSG_OOB 這個標志請求接收正常數據流中不會接收到的帶外數據。 一些協議將加急數據放在普通數據隊列的開頭,因此這標志不能與此類協議一起使用。
MSG_PEEK 這個標志使接收操作從接收隊列的開頭返回數據,而不會從隊列中刪除該數據。 因此,后續的接收呼叫將返回相同的數據。
MSG_TRUNC 對於原始(AF_PACKET),Internet數據報,netlink和UNIX數據報套接字:返回數據包或數據報的實際長度,即使它比傳遞的緩沖區長。
MSG_WAITALL 這個標志導致請求阻塞,直到滿足完整請求為止。 但是,如果捕獲到信號,發生錯誤或斷開連接,或者下一個要接收的數據與返回的數據類型不同,則呼叫返回的數據仍可能比請求的少。 這個標志對數據報套接字無效。
recvfrom()
recvfrom()將收到的消息放入緩沖區buf。 調用者必須指定緩沖區的大小。如果src_addr不為NULL,並且底層協議提供消息的源地址,則該源地址位於src_addr指向的緩沖區中。 在這種情況下,addrlen是一個值結果參數( a value-result argument)。 在調用之前,應將其初始化為src_addr緩沖區的大小。 返回時,addrlen則為源地址的實際大小。 如果提供的緩沖區太小,返回的地址將被截斷。 在這種情況下,addrlen將返回一個大於提供給調用的值。如果調用方對源地址不感興趣,則src_addr和addrlen應該指定為NULL。
recv()
recv()調用通常僅在面向連接的套接字上使用,等效於調用:recvfrom(fd,buf,len,flags,NULL,NULL)。
返回值
這些調用返回接收到的字節數,如果發生了錯誤則返回-1。 如果發生錯誤,則將errno設置為指示錯誤。當流套接字對等方執行有序關閉時,返回值將為0(傳統的“文件結束”返回)。各個域中的數據報套接字允許零長度的數據報。 收到這樣的數據報后,返回值為0。如果請求從流套接字接收的字節數為0,則也可能返回值0。