Windows Socket API

來源:互聯網
上載者:User

Windows Socket API 使用經驗
本文是我在進行MS-Windows、HP-unix網路編程的實踐過程中總結出來的一些經驗,僅供大家參考。本文所談到的Socket函數如果沒有特別說明,都是指的Windows Socket API。
一、WSAStartup函數
int WSAStartup(
WORD wVersionRequested,
LPWSADATA lpWSAData
);
使 用Socket的程式在使用Socket之前必須調用WSAStartup函數。該函數的第一個參數指明程式請求使用的Socket版本,其中高位位元組指 明副版本、低位位元組指明主要版本;作業系統利用第二個參數返回請求的Socket的版本資訊。當一個應用程式調用WSAStartup函數時,作業系統根據 請求的Socket版本來搜尋相應的Socket庫,然後綁定找到的Socket庫到該應用程式中。以後應用程式就可以調用所請求的Socket庫中的其 它Socket函數了。該函數執行成功後返回0。
例:假如一個程式要使用2.1版本的Socket,那麼程式碼如下
wVersionRequested = MAKEWORD( 2, 1 );
err = WSAStartup( wVersionRequested, &wsaData );

二、WSACleanup函數
int WSACleanup (void);
   應用程式在完成對請求的Socket庫的使用後,要調用WSACleanup函數來解除與Socket庫的綁定並且釋放Socket庫所佔用的系統資源。

三、socket函數
SOCKET socket(
int af,
int type,
int protocol
);
   應用程式調用socket函數來建立一個能夠進行網路通 信的通訊端。第一個參數指定應用程式使用的通訊協定的協議族,對於TCP/IP協議族,該參數置PF_INET;第二個參數指定要建立的通訊端類型,流套 接字類型為SOCK_STREAM、資料通訊端類型為SOCK_DGRAM;第三個參數指定應用程式所使用的通訊協定。
   該函數如果調用成功就返回新建立的通訊端的描述符,如果失敗就返回INVALID_SOCKET。通訊端描述符是一個整數類型的值。每個進程的進程空間裡 都有一個通訊端描述符表,該表中存放著通訊端描述符和通訊端資料結構的對應關係。該表中有一個欄位存放新建立的通訊端的描述符,另一個欄位存放通訊端資料 結構的地址,因此根據通訊端描述符就可以找到其對應的通訊端資料結構。每個進程在自己的進程空間裡都有一個通訊端描述符表但是通訊端資料結構都是在操作系 統的核心緩衝裡。下面是一個建立流通訊端的例子:
struct protoent *ppe;
ppe=getprotobyname("tcp");
SOCKET ListenSocket=socket(PF_INET,SOCK_STREAM,ppe->p_proto);

四、closesocket函數
int closesocket(
SOCKET s
);
closesocket 函數用來關閉一個描述符為s通訊端。由於每個進程中都有一個通訊端描述符表,表中的每個通訊端描述符都對應了一個位於作業系統緩衝區中的通訊端資料結構, 因此有可能有幾個通訊端描述符指向同一個通訊端資料結構。通訊端資料結構中專門有一個欄位存放該結構的被引用次數,即有多少個通訊端描述符指向該結構。當 調用closesocket函數時,作業系統先檢查通訊端資料結構中的該欄位的值,如果為1,就表明只有一個通訊端描述符指向它,因此作業系統就先把s在 通訊端描述符表中對應的那條表項清除,並且釋放s對應的通訊端資料結構;如果該欄位大於1,那麼作業系統僅僅清除s在通訊端描述符表中的對應表項,並且把 s對應的通訊端資料結構的引用次數減1。
closesocket函數如果執行成功就返回0,否則返回SOCKET_ERROR。

五、send函數
int send(
SOCKET s,
const char FAR *buf,
int len,
int flags
);
不 論是客戶還是伺服器應用程式都用send函數來向TCP串連的另一端發送資料。客戶程式一般用send函數向伺服器發送請求,而伺服器則通常用send函 數來向客戶程式發送應答。該函數的第一個參數指定發送端通訊端描述符;第二個參數指明一個存放應用程式要發送資料的緩衝區;第三個參數指明實際要發送的數 據的位元組數;第四個參數一般置0。這裡只描述同步Socket的send函數的執行流程。當調用該函數時,send先比較待發送資料的長度len和通訊端 s的發送緩衝區的長度,如果len大於s的發送緩衝區的長度,該函數返回SOCKET_ERROR;如果len小於或者等於s的發送緩衝區的長度,那麼 send先檢查協議是否正在發送s的發送緩衝中的資料,如果是就等待協議把資料發送完,如果協議還沒有開始發送s的發送緩衝中的資料或者s的發送緩衝中沒 有資料,那麼send就比較s的發送緩衝區的剩餘空間和len,如果len大於剩餘空間大小send就一直等待協議把s的發送緩衝中的資料發送完,如果 len小於剩餘空間大小send就僅僅把buf中的資料copy到剩餘空間裡(注意並不是send把s的發送緩衝中的資料傳到串連的另一端的,而是協議傳 的,send僅僅是把buf中的資料copy到s的發送緩衝區的剩餘空間裡)。如果send函數copy資料成功,就返回實際copy的位元組數,如果 send在copy資料時出現錯誤,那麼send就返回SOCKET_ERROR;如果send在等待協議傳送資料時網路斷開的話,那麼send函數也返回SOCKET_ERROR。要注意send函數把buf中的資料成功copy到s的發送緩衝的剩餘空間裡後它就返回了,但是此時這些資料並不一定馬上被傳到串連的另一端。如果協議在後續的傳送過程中出現網路錯誤的話,那麼下一個Socket函數就會返回SOCKET_ERROR。(每一個除send外的Socket函數在執行的最開始總要先等待通訊端的發送緩衝中的資料被協議傳送完畢才能繼續,如果在等待時出現網路錯誤,那麼該Socket函數就返回SOCKET_ERROR)
注意:在unix系統下,如果send在等待協議傳送資料時網路斷開的話,調用send的進程會接收到一個SIGPIPE訊號,進程對該訊號的預設處理是進程終止。

六、recv函數
int recv(
SOCKET s,
char FAR *buf,
int len,
int flags
);
不 論是客戶還是伺服器應用程式都用recv函數從TCP串連的另一端接收資料。該函數的第一個參數指定接收端通訊端描述符;第二個參數指明一個緩衝區,該緩 沖區用來存放recv函數接收到的資料;第三個參數指明buf的長度;第四個參數一般置0。這裡只描述同步Socket的recv函數的執行流程。當應用 程式調用recv函數時,recv先等待s的發送緩衝中的資料被協議傳送完畢,如果協議在傳送s的發送緩衝中的資料時出現網路錯 誤,那麼recv函數返回SOCKET_ERROR,如果s的發送緩衝中沒有資料或者資料被協議成功發送完畢後,recv先檢查通訊端s的接收緩衝區,如 果s接收緩衝區中沒有資料或者協議正在接收資料,那麼recv就一直等待,只到協議把資料接收完畢。當協議把資料接收完畢,recv函數就把s的接收緩衝 中的資料copy到buf中(注意協議接收到的資料可能大於buf的長度,所以在這種情況下要調用幾次recv函數才能把s的接收緩衝中的資料copy 完。recv函數僅僅是copy資料,真正的接收資料是協議來完成的),recv函數返回其實際copy的位元組數。如果recv在copy時出錯,那麼它 返回SOCKET_ERROR;如果recv函數在等待協議接收資料時網路中斷了,那麼它返回0。
注意:在unix系統下,如果recv函數在等待協議接收資料時網路斷開了,那麼調用recv的進程會接收到一個SIGPIPE訊號,進程對該訊號的預設處理是進程終止。

七、bind函數
int bind(
SOCKET s,
const struct sockaddr FAR *name,
int namelen
);
當 建立了一個Socket以後,通訊端資料結構中有一個預設的IP地址和預設的連接埠號碼。一個服務程式必須調用bind函數來給其綁定一個IP地址和一個特定 的連接埠號碼。客戶程式一般不必調用bind函數來為其Socket綁定IP地址和斷口號。該函數的第一個參數指定待綁定的Socket描述符;第二個參數指 定一個sockaddr結構,該結構是這樣定義的:
struct sockaddr {
u_short sa_family;
char sa_data[14];
};
sa_family指定地址族,對於TCP/IP協議族的通訊端,給其置AF_INET。當對TCP/IP協議族的通訊端進行綁定時,我們通常使用另一個地址結構: 
struct sockaddr_in {
short sin_family;
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
其 中sin_family置AF_INET;sin_port指明連接埠號碼;sin_addr結構體中只有一個唯一的欄位s_addr,表示IP地址,該欄位 是一個整數,一般用函數inet_addr()把字串形式的IP地址轉換成unsigned long型的整數值後再置給s_addr。有的伺服器是多重主機機,至少有兩個網卡,那麼運行在這樣的伺服器上的服務程式在為其Socket綁定IP地址時 可以把htonl(INADDR_ANY)置給s_addr,這樣做的好處是不論哪個網段上的客戶程式都能與該服務程式通訊;如果只給運行在多重主機機上的 服務程式的Socket綁定一個固定的IP地址,那麼就只有與該IP地址處於同一個網段上的客戶程式才能與該服務程式通訊。我們用0來填充 sin_zero數組,目的是讓sockaddr_in結構的大小與sockaddr結構的大小一致。下面是一個bind函數調用的例子:
struct sockaddr_in saddr;
saddr.sin_family = AF_INET;
saddr.sin_port = htons(8888);
saddr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(ListenSocket,(struct sockaddr *)&saddr,sizeof(saddr));

八、listen函數
int listen( SOCKET s, int backlog );
服務程式可以調用listen函數使其流通訊端s處於監聽狀態。處於監聽狀態的流通訊端s將維護一個客戶串連請求隊列,該隊列最多容納backlog個客戶串連請求。假如該函數執行成功,則返回0;如果執行失敗,則返回SOCKET_ERROR。

九、accept函數
SOCKET accept(
SOCKET s,
struct sockaddr FAR *addr,
int FAR *addrlen
);
服 務程式調用accept函數從處於監聽狀態的流通訊端s的客戶串連請求隊列中取出排在最前的一個客戶請求,並且建立一個新的通訊端來與客戶通訊端建立串連 通道,如果串連成功,就返回新建立的通訊端的描述符,以後與客戶通訊端交換資料的是新建立的通訊端;如果失敗就返回INVALID_SOCKET。該函數 的第一個參數指定處於監聽狀態的流通訊端;作業系統利用第二個參數來返回新建立的通訊端的地址結構;作業系統利用第三個參數來返回新建立的通訊端的地址結 構的長度。下面是一個調用accept的例子:
struct sockaddr_in ServerSocketAddr;
int addrlen;
addrlen=sizeof(ServerSocketAddr);
ServerSocket=accept(ListenSocket,(struct sockaddr *)&ServerSocketAddr,&addrlen);

十、connect函數
int connect(
SOCKET s,
const struct sockaddr FAR *name,
int namelen
);
客戶程式調用connect函數來使客戶Socket s與監聽於name所指定的電腦的特定連接埠上的服務Socket進行串連。如果串連成功,connect返回0;如果失敗則返回SOCKET_ERROR。下面是一個例子:
struct sockaddr_in daddr;
memset((void *)&daddr,0,sizeof(daddr));
daddr.sin_family=AF_INET;
daddr.sin_port=htons(8888);
daddr.sin_addr.s_addr=inet_addr("133.197.22.4");
connect(ClientSocket,(struct sockaddr *)&daddr,sizeof(daddr));
轉自:http://wangxiaojs.javaeye.com/blog/294578

              如何進行Socket編程(轉)
    進程通訊的概念最初來源於單機系統,由於每個進程都在各自的位址範圍內運行,為了保證兩個相互連信的進程之間既不互相干擾,又協調一致的工作,作業系統為進程通訊提供了相應設施,如UNIX BSD中的管道(pipe),有名管道(named pipe)和非強制中斷訊號(singal),UNIX system V的訊息(message)、共用儲存區(shared memory)和訊號量(semaphore)等,但都局限於用在本機進程之間通訊。網間進程通訊要解決的是不同主機處理序間的通訊問題(可把同機進程通訊看作其中的特例)。為此,首先要解決的是網間進程標識問題。同一主機上,不同進程可以用進程號(pid)唯一標識。但在網路環境下,各主機獨立分配的進程號不能唯一標識該進程。例如主機A賦予某進程號5,在B主機也可以存在5號進程,因此5號進程這句話就沒有意義了。其次,作業系統支援的網路通訊協定眾多,不同協議的工作方式不同,地址格式也不同。因此,網間進程通訊還要解決多重協議的識別問題。為瞭解決上述問題,TCP/IP協議引入了下列幾個概念。  
連接埠  
    網路中可以被命名和定址的通訊連接埠是作業系統可分配的一種資源。按照OSI七層協議的描述,傳輸層與網路層最大的區別是傳輸層提供進程通訊能力。從這個意義上講,網路通訊的最終地址就不僅是主機地址了,還包括可以描述進程的某種標識符。為此TCP/IP協議提出了協議連接埠的概念,用於標識通訊的進程。  
    連接埠是一種抽象的軟體結構,包括一些資料結構和I/O緩衝區。應用程式即進程通過系統調用與某連接埠建立串連(binding)後,傳輸層傳給該連接埠的資料都被相應的進程所接收,相應進程發給傳輸層的資料都從該連接埠輸出。在TCP/IP協議的實現中,連接埠操作類似於一般的I/O操作,進程擷取一個連接埠,相當於擷取本地唯一的I/O檔案,可以用一般的讀寫原語訪問。  
    類似於檔案描述符,每個連接埠都擁有一個叫連接埠號碼的整數描述符,以區別不同連接埠。由於TCP/IP傳輸層的兩個協議TCP和UDP是兩個完全獨立的軟體模組,因此各自的連接埠號碼也相互獨立。如TCP有一個255號連接埠,UDP也可以有一個255號連接埠,兩者並不衝突。  
    連接埠號碼的分配是一個重要問題,有兩種基本分配方式:第一種叫全域分配這是一種集中分配方式,由一個公認的中央機構根據使用者需要盡行統一分配,並將結果公佈於眾,第二種是本地分配,又稱動態串連,即進程需要訪問傳輸層服務時,向本地作業系統提出申請,作業系統返回本地唯一的連接埠號碼,進程再通過合適的系統調用,將自己和該連接埠串連起來(綁定)。TCP/IP連接埠號碼的分配綜合了兩種方式。TCP/IP將連接埠號碼分為兩部分,少量的作為保留連接埠,以全域方式分配給服務進程。因此,每一個標準伺服器都擁有一個全域公認的連接埠叫周知口,即使在不同的機器上,其連接埠號碼也相同。剩餘的為自由連接埠,以本地方式進行分配。TCP和UDP規定,小於256的連接埠才能作為保留連接埠。  
地址  
    網路通訊中的兩個進程分別在兩個不同的機器上。在互連網路中,兩台機器可以位於不同的網路,這些網路通過網際互連裝置(網關,橋接器,路由器)串連。因此需要三級定址。  
    1。某一主機與多個網路相連,必須指定一特定網路地址;  
    2。網路上美一台主機應有其唯一的地址;  
    3。美一主機上的每一進程應有在該主機上的唯一標識。  
    主機地址就是IP啦,不必多說。進程唯一識別碼是十六位整數連接埠號碼。  
網路位元組順序  
    不同的電腦存放多位元組值的順序不同,有的機器在起始地址存放低位位元組,有的則相反。為保證資料的正確性,在網路通訊協定中需指定網路位元組順序。TCP/IP協議使用16位整數和32位整數的高價先存格式,他們均含在協議的標頭檔中。  
串連  
    兩個進程間的通訊鏈路稱為串連。串連在內部表現為一些緩衝區和一組協議機制,在外部表格現出比無串連高的可靠性。  
半相關  
   綜上所述,網路中用一個三元組可以在全域中唯一標是一個進程:(協議,本機地址,本地連接埠號碼)這樣一個三元組,叫做一個半相關,他指定串連的每半部分。全相關  
    一個完整的網間進程通訊需要有兩個進程組成,並且只能使用同一種高層協議。也就是說TCP和UDP沒法通訊。因此一個完整的網間進程通訊需要一個五元組來標識:  
    (協議,本機地址,本地連接埠號碼,遠地地址,遠地連接埠號碼)這樣一個五元組叫做一個全相關。  
    在TCP/IP網路應用中,通訊的兩個進程相互作用的主要模式是客戶機/伺服器模式,即用戶端向伺服器發出請求,伺服器接收到請求後提供相應的服務客戶機/伺服器模式的建立基於以下兩點:首先,建立網路的起因是網路中軟、硬體資源、運算能力和資訊不均等,需要共用,從而造就擁有眾多資源的主機提供服務,資源較少的客戶請求服務這一非對等作用。其次,網間進程通訊完全是非同步,相互連信的進程間既不存在父子關係,又不共用記憶體緩衝區,因此需要一種機製為希望通訊的進程間建立一種聯絡,為二者的資料交換提供同步,這就是基於客戶機/伺服器模式的TCP/IP。  
    客戶機/伺服器模式在操作過程中採取的是主動請求方式:  
    首先伺服器方要啟動,並根據請求提供相應服務:  
    1。開啟一通訊通道並告知本地主機,它願意在某一公認地址連接埠上(周知口,如http為80)接受客戶請求。  
    2。等待客戶請求到達該連接埠。  
    3。接收到重複服務要求,處理該請求並發送應答訊號。接收並發服務要求,要啟用一新進程來處理這個客戶請求。新進程處理此客戶請求,並不需要對其他請求做出應答。服務完成後,關閉此新進程與客戶的通訊鏈路,並終止。  
    4。返回第二步,等待另外的客戶請求  
    5。關閉伺服器。  
    客戶方:  
    1。開啟一通訊通道,並串連到伺服器所在主機的特定連接埠。  
    2。向伺服器發出服務要求報文,等待並接收應答;繼續提出請求。  
    3。請求結束後關閉通訊通道並終止。  
    從上面的描述過程可知:  
    1。客戶與伺服器處理序的作用是非對稱的。因此編碼不同。  
    2。服務進程一般是先於客戶請求啟動的。只要系統運行,該進程一直存在,直到正常終止或者強迫終止。

    在UNIX世界中,網路應用編程介面有兩類:BSD的通訊端SOCKET和SYSTEM V的TLI.由於Sun公司採用了支援TCP/IP的BSD系統,TCP/IP的應用有了更大發展其網路應用編程介面Socket在網路編程中已成為標準。並且也早已經進入了MS的世界。  
    TCP/IP的Socket提供下列三種類型的通訊端  
    1。流式通訊端(SOCKET_STREAM)  
    提供了一個連線導向,可靠的Data Transmission Service,資料無差錯,無重複的發送且按發送順序接收。內設流量控制,避免資料流超限;資料被看作是位元組流,無長度限制。FTP協議即採用流式通訊端。  
    2。資料報式通訊端(SOCKET_DGRAM)  
    提供了一個無串連服務。資料包以獨立包形式被發送,不提供無錯保證,資料可能丟失或重複,並且接收順序無序。網路檔案系統NFS使用資料報式通訊端。  
    3。原始式通訊端(SOCKET_RAW)  
    該介面允許對較低層次協議,如IP、ICMP直接存取。常用於檢驗新的協議實現或訪問現有服務中配置的新裝置。  
基本通訊端調用  
    建立通訊端--socket();  
    綁定本機連接埠--bind();  
    建立串連--connect(),accept();  
    偵聽連接埠--listen();  
    資料轉送--send(),recv();  
    輸入/輸出多工--select();  
    關閉通訊端--closesocket();      
    不論何種語言,和socket打交道都是這一組調用只是在格式上有一點點差別。我只使用過c和perl,再加上這裡又不讓出現與perl無關的東西,那下面就主要討論PERL的socket編程啦:  
建立建通訊端:  
socket(SOC_VARIABLE,DOMAIN_FLAG,connectType,num)  #相應的C語言調用為sockid=socket(af,type,protocol)  
參數含義如下:  
SOC_VARIABLE是用於建立套接的控制代碼,相當於c裡面的sockid號;DOMAIN_FLAG叫域標記,在C裡相當於af--address family,地址族。地址族和域是一個概念,其實就是平常所說的域。UNIX支援的域類型有  
AF-UNIX;      UNIX內部地址  
   AF-INET;      TCP/IP地址  
   AF-NS;        Xerox NS地址  
   AF-APPLETALK; Apple的Appletalk地址  
而dos/windows支援的域地址族只有AF-INET.所以大部分的socket編程都只用到它。  
connectType(c裡的type)就是前面所說的三種socket類型。num相當於c裡面的protocol那大家一看就明白了這是協議號,用來指定SOCKET請求所希望的協議,這個參數不一定起作用,當前兩個參數可以確定協議時可以取值為零。  
所以,一個完整的PERL的建立socket如下  
socket(THESCK,AF-INET,SOCKET_STREAM,getprotocolbyname('tcp'));  
#c語言: int sockid;  
#        sockid = socket(AF-INET,SOCKET_STREAM,0);  
第二步了:bind()--綁定到本地地址。  
    第一步socket()調用只是指定了相關五元組的協議元。其他四元需要別的調用來補充。socket的建立可以認為建立了一個名字空間(地址族),但他沒有被命名。bind()將通訊端地址與本機建立的通訊端控制代碼(c裡面的通訊端號)綁定,即將名字賦予通訊端(控制代碼),以指定本地半相關。按照標準的socket來說(在UNIX世界裡所謂編程的"標準介面"就和說"c的編程介面"沒啥區別),通訊端地址是一個描述socket地址的資料結構。其中描述TCP/IP協議地址(AF_INET)的結構為:  
struct sockaddr_in{  
   short sin_family; //AF_INET  
   u_short sin_port; //16位連接埠號碼,網路位元組順序  
   struct in_addr sin_addr; //32位IP地址,網路位元組順序  
   char sin_zero[8]; //保留  
}  
其他的結構還有 sockaddr_ns,sockaddr_un等,是用在其他協議地址的。基本上我們用不到。於是一個標準綁定為:  
bind(SOCKET sockid,struct * localaddr_name,int addrlen);  
//sockid是一個未命名通訊端的socket號  
//localaddr_name是用來命名sockid的指向sockaddr_in結構的指標  
//addrlen是localaddr_name的位元組長度  
使用perl的bind()時先要調用inet_aton('localhost');或函數 INADDR_ANY 取得ip地址字串,然後調用  
$localaddr_port = sockaddr_in($port,inet_aton('localhost')); #$port是連接埠號碼  
或者是 $localaddr_port = sockaddr_in($port,INADDR_ANY); 獲得TCP/IP的地址,最後bind(SERVER,$localaddr_port);  
完成綁定!在這裡不用指定$localaddr_port的位元組長度,這就是perl的好處。  
    這兩個系統調用用於完成一個全相關的建立,其中connect()用於建立串連。accept()使伺服器等待來自某客戶進程的實際串連。其調用格式如下  
connect(SOCKET sockid,struct sockaddr* destaddr,int addrlen);  
//sockid是欲建立串連的本地socket號  
//destaddr是一個指向對方socket地址(信宿地址)結構的指標  
//addrlen是對方socket地址長度     
perl語言的connect()調用格式為:  
connect(SOC_VARIABLE,NAME_VARIABLE)  
具體的調用過程如下  
$remoteaddr_port = sockaddr_in($port,inet_aton('abc.efg.com'));  
connect(CLIENT,$remoteaddr_port); #半相關三元組(協議,遠地地址,遠地連接埠號碼)。 
可以發現connect()和bind()調用如出一轍,只是SERVER換成CLIENT,local換成remote,沒錯,他們的道理是一樣的,作用是互補的。他們各自建立了伺服器和客戶機方面的半相關。這時就要accept()來摻和一下一個完整的網間進程通訊的全相關就可以建立啦!(其實標準connect()還可以用於不需連線的socket調用。但這個用法比較左道,常把人搞暈點,所以就不說了)  
標準accept()調用:  
SOCKET newsock = accept(SOCKET sockid,struct sockaddr* clientaddr,int  addlen)  
  //sockid ,伺服器本地的socket號  
  //clientaddr ,指向客戶socket結構的指標。它的初始值為空白  
  //addlen ,客戶socket結構的位元組長度,它的初始值為0  
  //newsock ,accept()的傳回值,為一個新的socket號,可用於伺服器  //處理並發請求。伺服器fork一個子伺服器處理序,利用此socket號回 
  //答accept()所接收的客戶請求  
可以看出,accept()是連線導向的伺服器端的調用。他還將用戶端的socket地址及其位元組長度放在clientaddr和addlen以便為其他不需連線的調用指定信宿地址。但是,那些比較靈活但沒有原則的無串連用法在perl裡是沒有的,perl的用法認為socket必須是連線導向的,請看perl裡的accept():  
  accept(NEW_SOC_VARIABLE,CURRENT_SOC_VARIABLE);  
    可以看到accept()從當前的socket控制代碼上串連出一個用戶端到新的socket控制代碼。而它的傳回值用戶端的地址(信宿地址)。其實串連一旦建立,服務方無須知道信宿地址,只要向套口裡灌輸位元流就行了。這樣做的好處是使協議對於應用程式更加透明,易於理解。  
在調用accept()之前還應該先調用listen(),listen()的作用是偵聽連接埠,接收串連。如果不調用listen()的話,accept()將無法從當前socket"接"回與用戶端的串連。標準listen():  
    listen(sockid,quelen);  
    //socket號,伺服器願意從它上面接收請求  
    //quelen,請求隊列長度,listen()以此限制排隊請求的個數         
perl的liste():  
    listen(SOC_VARIABLE,num);#和C語言的版本很像哦        
    SOC_VARIABLE是socket控制代碼,num是請求隊列長度.  
    到這裡為止,一個串連的五元組都齊了。 
http://gnn.javaeye.com/blog/464862

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.