socket API詳解

來源:互聯網
上載者:User

標籤:style   color   使用   os   strong   檔案   資料   for   

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訊號,進程對該訊號的預設處理是進程終止。

使用inet_addr( )程式把諸如“ 132.241.5.10“形式的I P地址轉化為無符號的整型數。

ina.sin_addrs_addr = inet_addr("132.241.5.10");

如果出錯,inet_addr( )程式將返回- 1。
也可以調用inet_ntoa( )把地址轉換成數字和句點的形式:
printf( " % s " , inet_ntoa( ina.sin_addr ) ) ;
這將會列印出I P地址。它返回的是一個指向字串的指標。

socket()

我們使用系統調用socket()來獲得檔案描述符:

#include
#include
int socket(int domain, int type, int protocol);

第一個參數domain設定為“AF_INET”。
第二個參數是套介面的類型:SOCK_DGRAM。
第三個參數設定為0。
系統調用socket()只返回一個套介面描述符,如果出錯,則返回- 1。

bind()

一旦你有了一個套介面以後,下一步就是把套介面綁定到本機電腦的某一個連接埠上。但如果你只想使用connect( )則無此必要。
下面是系統調用bind( )的使用方法:

#include
#include
int bind(int sockfd, struct sockaddr *my_addr, int addrlen);

第一個參數sockfd 是由socket( )調用返回的套介面檔案描述符。
第二個參數my_addr 是指向資料結構sockaddr的指標。資料結構sockaddr中包括了關於你的地址、連接埠和IP地址的資訊。
第三個參數addrlen可以設定成sizeof(struct sockaddr)。下面是一個例子:

#include
#include
#include
#define MYPORT 3490
main ( )
{
int sockfd;
struct sockaddr_in my_addr; //說明一個sock地址結構
sockfd = socket(AF_INET, SOCK_STREAM, 0); /* 基本的建立UDP socket,最好進行一些檢查 */
my_addr.sin_family = AF_INET; /* 設定協議集,基於internet協議 */
my_addr.sin_port = htons(MYPORT); // 連接埠號碼
my_addr. sin_addr.s_addr = inet_addr("132.241.5.10");//將字串轉換成標準的地址格式
bzero(&(my_addr.sin_zero), 8); /* zero the rest of the struct */
/* don‘t forget your error checking for bind(): */
bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr));
//綁定監聽進程到該socket上

如果出錯,bind() 也返回- 1。
如果你使用connect()系統調用,那麼你不必知道你使用的連接埠號碼。當你調用connect()時,它檢查套介面是否已經綁定,如果沒有,它將會分配一個閒置連接埠。

sendto() 和recvfrom()

因為資料報套介面並不串連到遠端主機上,所以在發送資料包之前,我們必須首先給出目的地址,請看

int sendto(int sockfd, const void *msg, int len, unsigned int flags,
const struct sockaddr *to, int tolen);

除了兩個參數以外,其他的參數和系統調用s e n d ( )時相同。參數t o是指向包含目的I P地址和連接埠號碼的資料結構s o c k a d d r的指標。參數t o l e n可以設定為sizeof(struct sockaddr)。

系統調用sendto( )返回實際發送的位元組數,如果出錯則返回- 1。
系統調用recvfrom( )的使用方法也和r e c v ( )的十分近似:

int recvfrom(int sockfd, void *buf, int len, unsigned int flags
struct sockaddr *from, int *fromlen);

sockfd: 描述字
buff: 指向輸入緩衝器的指標
nbytes: 讀位元組大小
flag: 標誌:0
from :對方協議地址
addrlen: 對方協議地址長度

函數傳回值: 讀入資料的長度,可以為0.

參數from是指向本機電腦中包含源I P地址和連接埠號碼的資料結構sockaddr的指標。參數fromlen設定為sizeof(struct sockaddr)。

系統調用recvfrom ( )返回接收到的位元組數,如果出錯則返回- 1。

close() 和shutdown()

你可以使用close( )調用關閉串連的套介面檔案描述符:

close(sockfd) ;

這樣就不能再對此套介面做任何的讀寫操作了。

使用系統調用shutdown(),可有更多的控制權。它允許你在某一個方向切斷通訊,或者切斷雙方的通訊:

int shutdown(int sockfd, int how);

第一個參數是你希望切斷通訊的套介面檔案描述符。第二個參數h o w值如下:
0—Further receives are disallowed
1—Further sends are disallowed
2—Further sends and receives are disallowed (like close())
shutdown() 如果成功則返回0,如果失敗則返回- 1。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.