other languages
other sections
ACCEPT(2) | Linux Programmer's Manual | ACCEPT(2) |
NAME 名稱¶
accept - 在一個套接字上接收一個連接SYNOPSIS 概述¶
#include <sys/types.h>DESCRIPTION 描述¶
accept 函數用於基於連接的套接字 (SOCK_STREAM, SOCK_SEQPACKET 和 SOCK_RDM). 它從未完成連接隊列中取出第一個連接請求,創建一個和參數 s 屬性相同的連接套接字,並為這個套接字分配一個檔案描述符, 然後以這個描述符返回.新創建的描述符不再處於傾聽狀態.原 套接字 s 不受此調用的影響.注意任意一個檔案描述符標誌 (任何可以被 fcntl以參數 F_SETFL 設置的值,比如非阻塞式或者異步狀態)不會被 accept. 所繼承. 參數 s 是以 socket(2) 創建,用 bind(2) 綁定到一個本地地址,並且在調用了 listen(2). 之後正在偵聽一個連接的套接字. 參數 addr 是一個指向結構sockaddr的指針.這個結構體以連接實體地址填充. 所謂的連接實體,就是眾所周知的網路層.參數 addr 所傳遞的真正的地址格式依賴於所使用的套接字族. (參見 socket(2) 和各協議自己的手冊頁). addrlen 是一個實時參數: 它的大小應該能夠足以容納參數 addr 所指向的結構體;在函數返回時此參數將以字節數表示出返回地址的 實際長度.若 addr 使用NULL作為參數,addrlen將也被置為NULL. 如果隊列中沒有未完成連接套接字,並且套接字沒有標記為非阻塞式, accept 將阻塞直到一個連接到達.如果一個套接字被標記為非阻塞式而隊列 中沒有未完成連接套接字, accept 將返回EAGAIN. 使用 select(2) 或者 poll(2). 可以在一個套接字上有連接到來時產生事件.當嘗試一個新的連接時 套接字讀就緒,這樣我們就可以調用 accept 為這個連接獲得一個新的套接字.此外,你還可以設置套接字在喚醒時 接收到信號 SIGIO; 細節請參見 socket(7) 對於那些需要顯式確認的協議,比如 DECNet, accept 可以看作僅僅從隊列中取出下一個連接而不做確認.當在這個新的檔案 描述符上進行普通讀寫操作時暗示了確認,當關閉這個新的套接字時暗 示了拒絕.目前在Linux上只有DECNet有這樣 的含義.NOTES 注意¶
當接收到一個 SIGIO 信號或者 select(2) 或 poll(2) 返回讀就緒並不總是意味著有新連接在等待,因為連接可能在調用 accept 之前已經被異步網路錯誤或者其他線程所移除.如果發生這種情況, 那麼調用將阻塞並等待下一個連接的到來.為確保 accept 永遠不會阻塞,傳遞的套接字 s 需要置 O_NONBLOCK 標誌(參見 socket(7)).RETURN VALUE 返回值¶
此調用在發生錯誤時返回-1.若成功則返回一個非負整數標識這個 連接套接字.ERROR HANDLING 錯誤處理¶
Linux accept 將一個待處理網路錯誤代碼通過 accept 傳遞給新套接字 . 這種處理方式有別於其他的BSD套接字實現.為可靠操作,應用程式 必須在調用 accept 之後能夠檢測這些為協議定義的網路錯誤,並且以重試解決,就像 EAGAIN 一樣.對於TCP/IP這些網路錯誤是 ENETDOWN, EPROTO, ENOPROTOOPT, EHOSTDOWN, ENONET, EHOSTUNREACH, EOPNOTSUPP, 以及 ENETUNREACH.ERRORS 錯誤¶
- EAGAIN或者EWOULDBLOCK
- 套接字被標記為非阻塞,且當前沒有可接收的連接.
- EBADF
- 描述符非法.
- ENOTSOCK
- 描述符指向一個檔案,而不是一個套接字.
- EOPNOTSUPP
- 作為參數的套接字不是 SOCK_STREAM. 類型
- EFAULT
- 參數 addr 不在使用者可寫地址空間之內.
- EPERM
- 防火牆規則禁止連接.
- ENOBUFS,ENOMEM
- 沒有足夠記憶體. 這個錯誤一般來說意味著記憶體分配受套接字緩沖區所限, 而不是沒有系統記憶體.
CONFORMING TO 相容於¶
SVr4,4.4BSD( accept 函數首次出現於BSD 4.2). BSD手冊頁文件定義了五個可能的錯誤返回值 (EBADF, ENOTSOCK, EOPNOTSUPP, EWOULDBLOCK, EFAULT). SUSv2文件的定義是EAGAIN, EBADF, ECONNABORTED, EFAULT, EINTR, EINVAL, EMFILE, ENFILE, ENOBUFS, ENOMEM, ENOSR, ENOTSOCK, EOPNOTSUPP, EPROTO, EWOULDBLOCK. Linux accept不繼承像 O_NONBLOCK 這樣的套接字標誌. 這一點有別於其他的BSD套接字實現. 因此,程式應該在accept所返回的套接字上設置所有需要的標誌.NOTE 注意¶
函數 accept 的第三個參數原來被聲明為'int *'(在libc4和libc5以及其他很多系統中, 比如BSD 4.*,SunOS 4, SGI);POSIX 1003.1g草案試圖將其改變為 `size_t *',SunOS 5就是這麼做的. 後來的POSIX草案和Single Unix Specification以及glibc2使用了 `socklen_t *'. Quoting Linus Torvalds: 引自Linus Torvalds (譯注:這個家伙就是Linux的創始人,所以我保留了他老人家的原文, 僅將原文大意附後): I fails: only italicizes a single line _Any_ sane library _must_ have "socklen_t" be the same size as int. Anything else breaks any BSD socket layer stuff. POSIX initially _did_ make it a size_t, and I (and hopefully others, but obviously not too many) complained to them very loudly indeed. Making it a size_t is completely broken, exactly because size_t very seldom is the same size as "int" on 64-bit architectures, for example. And it _has_ to be the same size as "int" because that's what the BSD socket interface is. Anyway, the POSIX people eventually got a clue, and created "socklen_t". They shouldn't have touched it in the first place, but once they did they felt it had to have a named type for some unfathomable reason (probably somebody didn't like losing face over having done the original stupid thing, so they silently just renamed their blunder). 數據類型"socklen_t"和int應該具有相同的長度.否則就會破壞 BSD套接字層的填充.POSIX開始的時候用的是size_t, Linus Torvalds(他希望有更多的人,但顯然不是很多) 努力向他們解釋使用size_t是完全錯誤的,因為在64位結構中 size_t和int的長度是不一樣的,而這個參數(也就是accept函數 的第三參數)的長度必須和int一致,因為這是BSD套接字接口 標準.最終POSIX的那幫家伙找到了解決的辦法,那就是創造了 一個新的類型"socklen_t".Linux Torvalds說這是由於他們 發現了自己的錯誤但又不好意思向大家伙兒承認,所以另外 創造了一個新的數據類型.SEE ALSO 參見¶
bind(2), connect(2), listen(2), select(2), socket(2)[中文版維護人]¶
byeyear <love_my_love@263.net >[中文版最新更新]¶
2002.01.27《中國linux論壇man手冊頁翻譯計劃》:¶
http://cmpp.linuxforum.net7 May 1999 | Linux 2.2 Page |