久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Windows Socket API 使用經(jīng)驗(yàn) - 技術(shù)文檔 - VC文檔 - 網(wǎng)絡(luò)通訊 - 立華軟件園

 ShaneWu 2009-11-13
Windows Socket API 使用經(jīng)驗(yàn)
發(fā)表日期:2004-12-08 作者:[轉(zhuǎn)貼] 出處:CSDN  

                                      我的Windows Socket API 使用經(jīng)驗(yàn)
                                           文章作者:唐綱

本文是我在進(jìn)行MS-Windows,、HP-Unix網(wǎng)絡(luò)編程的實(shí)踐過(guò)程中總結(jié)出來(lái)的一些經(jīng)驗(yàn),,僅供大家參考。本文所談到的Socket函數(shù)如果沒(méi)有特別說(shuō)明,,都是指的Windows Socket API,。

一、WSAStartup函數(shù)
    int WSAStartup(
      WORD wVersionRequested,  
      LPWSADATA lpWSAData  
    );
   
使 用Socket的程序在使用Socket之前必須調(diào)用WSAStartup函數(shù),。該函數(shù)的第一個(gè)參數(shù)指明程序請(qǐng)求使用的Socket版本,,其中高位字節(jié)指 明副版本、低位字節(jié)指明主版本,;操作系統(tǒng)利用第二個(gè)參數(shù)返回請(qǐng)求的Socket的版本信息,。當(dāng)一個(gè)應(yīng)用程序調(diào)用WSAStartup函數(shù)時(shí),操作系統(tǒng)根據(jù) 請(qǐng)求的Socket版本來(lái)搜索相應(yīng)的Socket庫(kù),,然后綁定找到的Socket庫(kù)到該應(yīng)用程序中,。以后應(yīng)用程序就可以調(diào)用所請(qǐng)求的Socket庫(kù)中的其 它Socket函數(shù)了。該函數(shù)執(zhí)行成功后返回0,。
例:假如一個(gè)程序要使用2.1版本的Socket,那么程序代碼如下
            wVersionRequested = MAKEWORD( 2, 1 );
            err = WSAStartup( wVersionRequested, &wsaData );

二,、WSACleanup函數(shù)
    int WSACleanup (void);
    應(yīng)用程序在完成對(duì)請(qǐng)求的Socket庫(kù)的使用后,要調(diào)用WSACleanup函數(shù)來(lái)解除與Socket庫(kù)的綁定并且釋放Socket庫(kù)所占用的系統(tǒng)資源,。

三,、socket函數(shù)
  
SOCKET socket(
      int af,       
      int type,     
      int protocol  
    );
    應(yīng)用程序調(diào)用socket函數(shù)來(lái)創(chuàng)建一個(gè)能夠進(jìn)行網(wǎng)絡(luò)通信的套接字。第一個(gè)參數(shù)指定應(yīng)用程序使用的通信協(xié)議的協(xié)議族,,對(duì)于TCP/IP協(xié)議族,,該參數(shù)置 PF_INET;第二個(gè)參數(shù)指定要?jiǎng)?chuàng)建的套接字類(lèi)型,流套接字類(lèi)型為SOCK_STREAM,、數(shù)據(jù)報(bào)套接字類(lèi)型為SOCK_DGRAM,;第三個(gè)參數(shù)指定應(yīng) 用程序所使用的通信協(xié)議。該函數(shù)如果調(diào)用成功就返回新創(chuàng)建的套接字的描述符,,如果失敗就返回INVALID_SOCKET,。套接字描述符是一個(gè)整數(shù)類(lèi)型的 值。每個(gè)進(jìn)程的進(jìn)程空間里都有一個(gè)套接字描述符表,,該表中存放著套接字描述符和套接字?jǐn)?shù)據(jù)結(jié)構(gòu)的對(duì)應(yīng)關(guān)系,。該表中有一個(gè)字段存放新創(chuàng)建的套接字的描述符, 另一個(gè)字段存放套接字?jǐn)?shù)據(jù)結(jié)構(gòu)的地址,,因此根據(jù)套接字描述符就可以找到其對(duì)應(yīng)的套接字?jǐn)?shù)據(jù)結(jié)構(gòu),。每個(gè)進(jìn)程在自己的進(jìn)程空間里都有一個(gè)套接字描述符表但是套 接字?jǐn)?shù)據(jù)結(jié)構(gòu)都是在操作系統(tǒng)的內(nèi)核緩沖里,。下面是一個(gè)創(chuàng)建流套接字的例子:
       
struct protoent *ppe;
        ppe=getprotobyname("tcp");
        SOCKET ListenSocket=socket(PF_INET,SOCK_STREAM,ppe->p_proto);

四、closesocket函數(shù)
  
int closesocket(
      SOCKET s  
    );
    closesocket函數(shù)用來(lái)關(guān)閉一個(gè)描述符為s套接字,。由于每個(gè)進(jìn)程中都有一個(gè)套接字描述符表,,表中的每個(gè)套接字描述符都對(duì)應(yīng)了一個(gè)位于操作系統(tǒng)緩沖 區(qū)中的套接字?jǐn)?shù)據(jù)結(jié)構(gòu),因此有可能有幾個(gè)套接字描述符指向同一個(gè)套接字?jǐn)?shù)據(jù)結(jié)構(gòu),。套接字?jǐn)?shù)據(jù)結(jié)構(gòu)中專(zhuān)門(mén)有一個(gè)字段存放該結(jié)構(gòu)的被引用次數(shù),,即有多少個(gè)套接 字描述符指向該結(jié)構(gòu)。當(dāng)調(diào)用closesocket函數(shù)時(shí),,操作系統(tǒng)先檢查套接字?jǐn)?shù)據(jù)結(jié)構(gòu)中的該字段的值,,如果為1,就表明只有
一個(gè)套接字描述符指向它,因此操作系統(tǒng)就先把s在套接字描述符表中對(duì)應(yīng)的那條表項(xiàng)清除,并且釋放s對(duì)應(yīng)的套接字?jǐn)?shù)據(jù)結(jié)構(gòu),;如果該字段大于1,那么操作系統(tǒng)僅僅清除s在套接字描述符表中的對(duì)應(yīng)表項(xiàng),,并且把s對(duì)應(yīng)的套接字?jǐn)?shù)據(jù)結(jié)構(gòu)的引用次數(shù)減1。
closesocket函數(shù)如果執(zhí)行成功就返回0,,否則返回SOCKET_ERROR,。

五、send函數(shù)
  
int send(
      SOCKET s,              
      const char FAR *buf,  
      int len,               
      int flags              
    );
    不論是客戶(hù)還是服務(wù)器應(yīng)用程序都用send函數(shù)來(lái)向TCP連接的另一端發(fā)送數(shù)據(jù),??蛻?hù)程序一般用send函數(shù)向服務(wù)器發(fā)送請(qǐng)求,而服務(wù)器則通常用send 函數(shù)來(lái)向客戶(hù)程序發(fā)送應(yīng)答,。該函數(shù)的第一個(gè)參數(shù)指定發(fā)送端套接字描述符,;第二個(gè)參數(shù)指明一個(gè)存放應(yīng)用程序要發(fā)送數(shù)據(jù)的緩沖區(qū);第三個(gè)參數(shù)指明實(shí)際要發(fā)送的 數(shù)據(jù)的字節(jié)數(shù),;第四個(gè)參數(shù)一般置0,。這里只描述同步Socket的send函數(shù)的執(zhí)行流程。當(dāng)調(diào)用該函數(shù)時(shí),,send先比較待發(fā)送數(shù)據(jù)的長(zhǎng)度len和套接 字s的發(fā)送緩沖區(qū)的長(zhǎng)度,,如果len大于s的發(fā)送緩沖區(qū)的長(zhǎng)度,該函數(shù)返回SOCKET_ERROR,;如果len小于或者等于s的發(fā)送緩沖區(qū)的長(zhǎng)度,,那么 send先檢查協(xié)議是否正在發(fā)送s的發(fā)送緩沖中的數(shù)據(jù),如果是就等待協(xié)議把數(shù)據(jù)發(fā)送完,,如果協(xié)議還沒(méi)有開(kāi)始發(fā)送s的發(fā)送緩沖中的數(shù)據(jù)或者s的發(fā)送緩沖中沒(méi) 有數(shù)據(jù),,那么send就比較s的發(fā)送緩沖區(qū)的剩余空間和len,如果len大于剩余空間大小send就一直等待協(xié)議把s的發(fā)送緩沖中的數(shù)據(jù)發(fā)送完,,如果 len小于剩余空間大小send就僅僅把buf中的數(shù)據(jù)copy到剩余空間里(注意并不是send把s的發(fā)送緩沖中的數(shù)據(jù)傳到連接的另一端的,,而是協(xié)議傳 的,,send僅僅是把buf中的數(shù)據(jù)copy到s的發(fā)送緩沖區(qū)的剩余空間里)。如果send函數(shù)copy數(shù)據(jù)成功,,就返回實(shí)際copy的字節(jié)數(shù),如果 send在copy數(shù)據(jù)時(shí)出現(xiàn)錯(cuò)誤,,那么send就返回SOCKET_ERROR,;如果send在等待協(xié)議傳送數(shù)據(jù)時(shí)網(wǎng)絡(luò)斷開(kāi)的話(huà),那么send函數(shù)也返 回SOCKET_ERROR,。要注意send函數(shù)把buf中的數(shù)據(jù)成功copy到s的發(fā)送緩沖的剩余空間里后它就返回了,,但是此時(shí)這些數(shù)據(jù)并不一定馬上被 傳到連接的另一端。如果協(xié)議在后續(xù)的傳送過(guò)程中出現(xiàn)網(wǎng)絡(luò)錯(cuò)誤的話(huà),,那么下一個(gè)Socket函數(shù)就會(huì)返回SOCKET_ERROR,。(每一個(gè)除send外的 Socket函數(shù)在執(zhí)行的最開(kāi)始總要先等待套接字的發(fā)送緩沖中的數(shù)據(jù)被協(xié)議傳送完畢才能繼續(xù),如果在等待時(shí)出現(xiàn)網(wǎng)絡(luò)錯(cuò)誤,,那么該Socket函數(shù)就返回 SOCKET_ERROR)
注意:在Unix系統(tǒng)下,,如果send在等待協(xié)議傳送數(shù)據(jù)時(shí)網(wǎng)絡(luò)斷開(kāi)的話(huà),調(diào)用send的進(jìn)程會(huì)接收到一個(gè)SIGPIPE信號(hào),,進(jìn)程對(duì)該信號(hào)的默認(rèn)處理是進(jìn)程終止,。

六、recv函數(shù)
    int recv(
      SOCKET s,       
      char FAR *buf,  
      int len,        
      int flags       
    );
    不論是客戶(hù)還是服務(wù)器應(yīng)用程序都用recv函數(shù)從TCP連接的另一端接收數(shù)據(jù),。該函數(shù)的第一個(gè)參數(shù)指定接收端套接字描述符,;第二個(gè)參數(shù)指明一個(gè)緩沖區(qū),該 緩沖區(qū)用來(lái)存放recv函數(shù)接收到的數(shù)據(jù),;第三個(gè)參數(shù)指明buf的長(zhǎng)度,;第四個(gè)參數(shù)一般置0。這里只描述同步Socket的recv函數(shù)的執(zhí)行流程,。當(dāng)應(yīng) 用程序調(diào)用recv函數(shù)時(shí),,recv先等待s的發(fā)送緩沖中的數(shù)據(jù)被協(xié)議傳送完畢,如果協(xié)議在傳送s的發(fā)送緩沖中的數(shù)據(jù)時(shí)出現(xiàn)網(wǎng)絡(luò)錯(cuò)誤,,那么recv函數(shù)返 回SOCKET_ERROR,,如果s的發(fā)送緩沖中沒(méi)有數(shù)據(jù)或者數(shù)據(jù)被協(xié)議成功發(fā)送完畢后,recv先檢查套接字s的接收緩沖區(qū),,如果s接收緩沖區(qū)中沒(méi)有數(shù) 據(jù)或者協(xié)議正在接收數(shù)據(jù),,那么recv就一直等待,只到協(xié)議把數(shù)據(jù)接收完畢,。當(dāng)協(xié)議把數(shù)據(jù)接收完畢,,recv函數(shù)就把s的接收緩沖中的數(shù)據(jù)copy到 buf中(注意協(xié)議接收到的數(shù)據(jù)可能大于buf的長(zhǎng)度,所以在這種情況下要調(diào)用幾次recv函數(shù)才能把s的接收緩沖中的數(shù)據(jù)copy完,。recv函數(shù)僅僅 是copy數(shù)據(jù),,真正的接收數(shù)據(jù)是協(xié)議來(lái)完成的),,recv函數(shù)返回其實(shí)際copy的字節(jié)數(shù)。如果recv在copy時(shí)出錯(cuò),,那么它返回 SOCKET_ERROR,;如果recv函數(shù)在等待協(xié)議接收數(shù)據(jù)時(shí)
網(wǎng)絡(luò)中斷了,那么它返回0,。
注意:在Unix系統(tǒng)下,,如果recv函數(shù)在等待協(xié)議接收數(shù)據(jù)時(shí)網(wǎng)絡(luò)斷開(kāi)了,那么調(diào)用recv的進(jìn)程會(huì)接收到一個(gè)
SIGPIPE信號(hào),,進(jìn)程對(duì)該信號(hào)的默認(rèn)處理是進(jìn)程終止,。

七、bind函數(shù)
  
int bind(
      SOCKET s,                          
      const struct sockaddr FAR *name,   
      int namelen                        
    );
    當(dāng)創(chuàng)建了一個(gè)Socket以后,,套接字?jǐn)?shù)據(jù)結(jié)構(gòu)中有一個(gè)默認(rèn)的IP地址和默認(rèn)的端口號(hào),。一個(gè)服務(wù)程序必須調(diào)用bind函數(shù)來(lái)給其綁定一個(gè)IP地址和一個(gè)特 定的端口號(hào)??蛻?hù)程序一般不必調(diào)用bind函數(shù)來(lái)為其Socket綁定IP地址和斷口號(hào),。該函數(shù)的第一個(gè)參數(shù)指定待綁定的Socket描述符;第二個(gè)參數(shù) 指定一個(gè)sockaddr結(jié)構(gòu),,該結(jié)構(gòu)是這樣定義的:
        struct sockaddr { 
            u_short sa_family; 
            char sa_data[14]; 
        };
   sa_family指定地址族,,對(duì)于TCP/IP協(xié)議族的套接字,給其置AF_INET,。當(dāng)對(duì)TCP/IP協(xié)議族的套接字進(jìn)行綁定時(shí),,我們通常使用另一個(gè)地址結(jié)構(gòu):
   
     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指明端口號(hào),;sin_addr結(jié)構(gòu)體中只有一個(gè)唯一的字段s_addr,,表示IP地址,該字 段是一個(gè)整數(shù),,一般用函數(shù)inet_addr()把字符串形式的IP地址轉(zhuǎn)換成unsigned long型的整數(shù)值后再置給s_addr,。有的服務(wù)器是多宿主機(jī),至少有兩個(gè)網(wǎng)卡,,那么運(yùn)行在這樣的服務(wù)器上的服務(wù)程序在為其Socket綁定IP地址時(shí) 可以把htonl(INADDR_ANY)置給s_addr,,這樣做的好處是不論哪個(gè)網(wǎng)段上的客戶(hù)程序都能與該服務(wù)程序通信;如果只給運(yùn)行在多宿主機(jī)上的 服務(wù)程序的Socket綁定一個(gè)固定的IP地址,,那么就只有與該IP地址處于同一個(gè)網(wǎng)段上的客戶(hù)程序才能與該服務(wù)程序通信,。我們用0來(lái)填充 sin_zero數(shù)組,目的是讓sockaddr_in結(jié)構(gòu)的大小與sockaddr結(jié)構(gòu)的大小一致,。下面是一個(gè)bind函數(shù)調(diào)用的例子:
    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函數(shù)
    int listen( SOCKET s, int backlog );
    服務(wù)程序可以調(diào)用listen函數(shù)使其流套接字s處于監(jiān)聽(tīng)狀態(tài),。處于監(jiān)聽(tīng)狀態(tài)的流套接字s將維護(hù)一個(gè)客戶(hù)連接請(qǐng)求隊(duì)列,,該隊(duì)列最多容納backlog個(gè)客戶(hù)連接請(qǐng)求。假如該函數(shù)執(zhí)行成功,,則返回0,;如果執(zhí)行失敗,則返回SOCKET_ERROR,。

九,、accept函數(shù)
   
SOCKET accept(
      SOCKET s, 
      struct sockaddr FAR *addr,  
      int FAR *addrlen  
    );
    服務(wù)程序調(diào)用accept函數(shù)從處于監(jiān)聽(tīng)狀態(tài)的流套接字s的客戶(hù)連接請(qǐng)求隊(duì)列中取出排在最前的一個(gè)客戶(hù)請(qǐng)求,并且創(chuàng)建一個(gè)新的套接字來(lái)與客戶(hù)套接字創(chuàng)建連 接通道,,如果連接成功,就返回新創(chuàng)建的套接字的描述符,,以后與客戶(hù)套接字交換數(shù)據(jù)的是新創(chuàng)建的套接字,;如果失敗就返回INVALID_SOCKET。該函 數(shù)的第一個(gè)參數(shù)指定處于監(jiān)聽(tīng)狀態(tài)的流套接字,;操作系統(tǒng)利用第二個(gè)參數(shù)來(lái)返回新創(chuàng)建的套接字的地址結(jié)構(gòu),;操作系統(tǒng)利用第三個(gè)參數(shù)來(lái)返回新創(chuàng)建的套接字的地址 結(jié)構(gòu)的長(zhǎng)度。下面是一個(gè)調(diào)用accept的例子:
        struct sockaddr_in ServerSocketAddr;
        int addrlen;
        addrlen=sizeof(ServerSocketAddr);
        ServerSocket=accept(ListenSocket,(struct sockaddr *)&ServerSocketAddr,&addrlen);

十,、connect函數(shù)
    int connect(
      SOCKET s,                          
      const struct sockaddr FAR *name,  
      int namelen                        
    );
    客戶(hù)程序調(diào)用connect函數(shù)來(lái)使客戶(hù)Socket s與監(jiān)聽(tīng)于name所指定的計(jì)算機(jī)的特定端口上的服務(wù)Socket進(jìn)行連接,。如果連接成功,connect返回0,;如果失敗則返回SOCKET_ERROR,。下面是一個(gè)例子:
        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));

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶(hù)發(fā)布,,不代表本站觀(guān)點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購(gòu)買(mǎi)等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多