send() - Unix 和 Linux 系統呼叫 - 技術教學
Tutorials Point


  Unix 初學者指南
  Unix Shell 程式設計
  高階 Unix
  Unix 有用參考
  Unix 有用資源
  精選閱讀

版權所有 © 2014 tutorialspoint



  首頁     參考     討論論壇     關於 TP  

send() - Unix 和 Linux 系統呼叫


previous next AddThis Social Bookmark Button

廣告

名稱

send、sendto、sendmsg - 在套接字上傳送訊息

語法

#include <sys/types.h>
#include <sys/socket.h>

ssize_t send(int s, const void *buf, size_t len, int flags);
ssize_t sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen);
ssize_t sendmsg(int s, const struct msghdr *msg, int flags);

描述

系統呼叫 send()、sendto() 和 sendmsg() 用於將訊息傳輸到另一個套接字。

只有當套接字處於 已連線 狀態(以便知道預期的接收者)時,才能使用 send() 呼叫。send() 和 write() 之間的唯一區別是 flags 的存在。當 flags 引數為零時,send() 等效於 write()。此外,send(s,buf,len,flags) 等效於 sendto(s,buf,len,flags,NULL,0)。

引數 s 是傳送套接字的檔案描述符。

如果在連線模式(SOCK_STREAM、SOCK_SEQPACKET)套接字上使用 sendto(),則引數 totolen 將被忽略(並且當它們不為 NULL 和 0 時可能會返回錯誤 EISCONN),並且當套接字實際上未連線時會返回錯誤 ENOTCONN。否則,目標的地址由 to 給出,tolen 指定其大小。對於 sendmsg(),目標的地址由 msg.msg_name 給出,msg.msg_namelen 指定其大小。

對於 send() 和 sendto(),訊息位於 buf 中,長度為 len。對於 sendmsg(),訊息由陣列 msg.msg_iov 的元素指向。sendmsg() 呼叫還允許傳送輔助資料(也稱為控制資訊)。

如果訊息太長而無法透過底層協議原子地傳遞,則會返回錯誤 EMSGSIZE,並且不會傳輸訊息。

send() 中沒有隱含的傳遞失敗指示。本地檢測到的錯誤由返回值 -1 指示。

當訊息不適合套接字的傳送緩衝區時,send() 通常會阻塞,除非套接字已置於非阻塞 I/O 模式。在這種情況下,在非阻塞模式下它將返回 EAGAIN。可以使用 select(2) 呼叫來確定何時可以傳送更多資料。

flags 引數是以下標誌的按位 OR。

標籤描述
MSG_CONFIRM(僅限 Linux 2.3+)
 告訴鏈路層發生了轉發進度:您從另一端獲得了成功的回覆。如果鏈路層沒有收到此資訊,它將定期探測鄰居(例如,透過單播 ARP)。僅在 SOCK_DGRAMSOCK_RAW 套接字上有效,目前僅在 IPv4 和 IPv6 上實現。有關詳細資訊,請參閱 arp(7)。
MSG_DONTROUTE
 不要使用閘道器傳送資料包,僅傳送到直接連線網路上的主機。這通常僅由診斷或路由程式使用。這僅針對路由的協議族定義;資料包套接字沒有。
MSG_DONTWAIT
 啟用非阻塞操作;如果操作將阻塞,則返回 EAGAIN(這也可以使用 O_NONBLOCKF_SETFL fcntl(2) 啟用)。
MSG_EOR
 終止記錄(當此概念受支援時,例如對於型別為 SOCK_SEQPACKET 的套接字)。
MSG_MORE(自 Linux 2.4.4 起)
 呼叫者有更多資料要傳送。此標誌與 TCP 套接字一起使用以獲得與 TCP_CORK 套接字選項相同的效果(請參閱 tcp(7)),區別在於此標誌可以在每個呼叫基礎上設定。

自 Linux 2.6 起,此標誌也受 UDP 套接字支援,並通知核心將使用此標誌設定的所有傳送資料打包到單個數據報中,該資料報僅在執行未指定此標誌的呼叫時傳輸。(另請參閱 udp(7) 中描述的 UDP_CORK 套接字選項)。

MSG_NOSIGNAL
 請求在流式套接字上發生錯誤時不要傳送 SIGPIPE,當另一端斷開連線時。EPIPE 錯誤仍然返回。
MSG_OOB
 在支援此概念的套接字(例如型別為 SOCK_STREAM 的套接字)上傳送 帶外 資料;底層協議也必須支援 帶外 資料。
msghdr 結構的定義如下。有關其欄位的確切描述,請參閱 recv(2) 和以下內容。

struct msghdr { void *msg_name; /* optional address */ socklen_t msg_namelen; /* size of address */ struct iovec *msg_iov; /* scatter/gather array */ size_t msg_iovlen; /* # elements in msg_iov */ void *msg_control; /* ancillary data, see below */ socklen_t msg_controllen; /* ancillary data buffer len */ int msg_flags; /* flags on received message */ };

您可以使用 msg_controlmsg_controllen 成員傳送控制資訊。核心可以處理的最大控制緩衝區長度受 net.core.optmem_max sysctl 限制;請參閱 socket(7)。

返回值

成功時,這些呼叫返回傳送的字元數。發生錯誤時,返回 -1,並且 errno 設定為適當的值。

錯誤

這些是套接字層生成的一些標準錯誤。其他錯誤可能會由底層協議模組生成和返回;請參閱它們各自的手冊頁。
標籤描述
EACCES (對於由路徑名標識的 Unix 域套接字)目標套接字檔案上拒絕寫入許可權,或者路徑字首中的一個目錄上拒絕搜尋許可權。(請參閱 path_resolution(2)。)
EAGAINEWOULDBLOCK
 套接字被標記為非阻塞,並且請求的操作將阻塞。
EBADF 指定了無效的描述符。
ECONNRESET
 連線被對等方重置。
EDESTADDRREQ
 套接字不是連線模式,並且未設定對等方地址。
EFAULT 為引數指定了無效的使用者空間地址。
EINTR 在任何資料傳輸之前發生了訊號。
EINVAL 傳遞了無效的引數。
EISCONN
 連線模式套接字已連線,但指定了接收者。(現在要麼返回此錯誤,要麼忽略接收者規範)。
EMSGSIZE
 套接字型別要求以原子方式傳送訊息,並且要傳送的訊息的大小使得這成為不可能。
ENOBUFS
 網路介面的輸出佇列已滿。這通常表示介面已停止傳送,但也可能是由瞬態擁塞引起的。(通常,這不會在 Linux 中發生。當裝置佇列溢位時,資料包只是被靜默丟棄)。
ENOMEM 沒有可用的記憶體。
ENOTCONN
 套接字未連線,並且未給出目標。
ENOTSOCK
 引數 s 不是套接字。
EOPNOTSUPP
 flags 引數中的一些位不適用於套接字型別。
EPIPE 在面向連線的套接字上,本地端已關閉。在這種情況下,程序也將接收 SIGPIPE,除非設定了 MSG_NOSIGNAL

符合標準

4.4BSD、SVr4、POSIX.1-2001。這些函式調用出現在 4.2BSD 中。

POSIX.1-2001 僅描述 MSG_OOBMSG_EOR 標誌。MSG_CONFIRM 標誌是 Linux 擴充套件。

註釋

上面給出的原型遵循 Single Unix Specification,就像 glibc2 一樣;flags 引數在 4.x BSD 中為 'int',但在 libc4 和 libc5 中為 'unsigned int';len 引數在 4.x BSD 和 libc4 中為 'int',但在 libc5 中為 'size_t';tolen 引數在 4.x BSD 和 libc4 和 libc5 中為 'int'。另請參閱 accept(2)。

根據 POSIX.1-2001,msghdr 結構的 msg_controllen 欄位應型別化為 socklen_t,但 glibc 當前(2.4)將其型別化為 size_t

錯誤

Linux 可能會返回 EPIPE 而不是 ENOTCONN。

另請參閱



previous next Printer Friendly

廣告


  

廣告



廣告