1. 程式人生 > >socket程式設計之accept()函式

socket程式設計之accept()函式

名稱

accept()

接收一個套接字中已建立的連線

使用格式

#include <sys/socket.h>

int accept(int sockfd,struct sockaddr *addr,socklen_t *addrlen);

功能引數描述

accept()系統呼叫主要用在基於連線的套接字型別,比如SOCK_STREAM和SOCK_SEQPACKET。它提取出所監聽套接字的等待連線佇列中第一個連線請求建立一個新的套接字,並返回指向該套接字的檔案描述符。新建立的套接字不在監聽狀態,原來所監聽的套接字也不受該系統呼叫的影響。

備註:新建立的套接字準備傳送send()和接收資料recv()。


引數:

sockfd,    利用系統呼叫socket()建立的套接字描述符,通過bind()繫結到一個本地地址(一般為伺服器的套接字),並且通過listen()一直在監聽連線

addr,    指向struct sockaddr的指標,該結構用通訊層伺服器對等套接字的地址(一般為客戶端地址)填寫,返回地址addr的確切格式由套接字的地址類別(比如TCP或UDP)決定;若addr為NULL,沒有有效地址填寫,這種情況下,addrlen也不使用,應該置為NULL;

備註:addr是個指向區域性資料結構sockaddr_in的指標,這就是要求接入的資訊本地的套接字(地址和指標)。

addrlen

,    一個值結果引數,呼叫函式必須初始化為包含addr所指向結構大小的數值,函式返回時包含對等地址(一般為伺服器地址)的實際數值;

備註:addrlen是個區域性整形變數,設定為sizeof(struct   sockaddr_in)。

如果佇列中沒有等待的連線,套接字也沒有被標記為Non-blocking,accept()會阻塞呼叫函式直到連接出現;如果套接字被標記為Non-blocking,佇列中也沒有等待的連線,accept()返回錯誤EAGAINEWOULDBLOCK

備註:一般來說,實現時accept()為阻塞函式,當監聽socket呼叫accept()時,它先到自己的receive_buf中檢視是否有連線資料包;

若有,把資料拷貝出來,刪掉接收到的資料包,建立新的socket與客戶發來的地址建立連線;

若沒有,就阻塞等待;

為了在套接字中有到來的連線時得到通知,可以使用select()或poll()。當嘗試建立新連線時,系統傳送一個可讀事件,然後呼叫accept()為該連接獲取套接字。另一種方法是,當套接字中有連線到來時設定套接字傳送SIGIO訊號。

返回值

成功時,返回非負整數,該整數是接收到套接字的描述符;出錯時,返回-1,相應地設定全域性變數errno。

錯誤處理

Linux下,accept()把已等待的網路錯誤傳給新建立的連線,當作是accept()返回的錯誤。這於其他的BSD實現是不同的。為了可靠執行,應該在accept()之後檢測協議已定義的一些網路錯誤,並把這些錯誤當作EAGAIN並重試。對於TCP/IP協議來說,主要有錯誤:ENETDOWN,EPROTO,ENOPROTOOPT,EHOSTDOWN,ENONET,EHOSTUNREACH,EOPNOTSUPPENETUNREACH