欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

socket編程的詳細(xì)講解

 更新時(shí)間:2021年08月18日 11:53:22   作者:楓飛飛  
本文詳細(xì)講解了socket編程,它是網(wǎng)絡(luò)中經(jīng)常使用的一門技術(shù),該文章通過(guò)大量的代碼來(lái)解釋,大家可以參考參考

socket編程是網(wǎng)絡(luò)常用的編程,我們通過(guò)在網(wǎng)絡(luò)中創(chuàng)建socket關(guān)鍵字來(lái)實(shí)現(xiàn)網(wǎng)絡(luò)間的通信,通過(guò)收集大量的資料,通過(guò)這一章節(jié),充分的了解socket編程,文章用引用了大量大神的分析,加上自己的理解,做個(gè)總結(jié)性的文章

1:socket大致介紹

      socket編程是一門技術(shù),它主要是在網(wǎng)絡(luò)通信中經(jīng)常用到

      既然是一門技術(shù),由于現(xiàn)在是面向?qū)ο蟮木幊?,一些?jì)算機(jī)行業(yè)的大神通過(guò)抽象的理念,在現(xiàn)實(shí)中通過(guò)反復(fù)的理論或者實(shí)際的推導(dǎo),提出了抽象的一些通信協(xié)議,基于tcp/ip協(xié)議,提出大致的構(gòu)想,一些泛型的程序大牛在這個(gè)協(xié)議的基礎(chǔ)上,將這些抽象化的理念接口化,針對(duì)協(xié)議提出的每個(gè)理念,專門的編寫制定的接口,與其協(xié)議一一對(duì)應(yīng),形成了現(xiàn)在的socket標(biāo)準(zhǔn)規(guī)范,然后將其接口封裝成可以調(diào)用的接口,供開發(fā)者使用

     目前,開發(fā)者開發(fā)出了很多封裝的類來(lái)完善socket編程,都是更加方便的實(shí)現(xiàn)剛開始socket通信的各個(gè)環(huán)節(jié),所以我們首先必須了解socket的通信原理,只有從本質(zhì)上理解socket的通信,才可能快速方便的理解socket的各個(gè)環(huán)節(jié),才能從底層上真正的把握

2:TCP/IP協(xié)議

     要理解socket必須的得理解tcp/ip,它們之間好比送信的線路和驛站的作用,比如要建議送信驛站,必須得了解送信的各個(gè)細(xì)節(jié)。

     TCP/IP協(xié)議不同于iso的7個(gè)分層,它是根據(jù)這7個(gè)分層,將其重新劃分,好比打掃衛(wèi)生,本來(lái)有掃帚,垃圾斗,抹布,涂料,盆栽等就好比OSI的標(biāo)準(zhǔn)幾個(gè)分層,tcp/ip根據(jù)用途和功能,將掃帚,垃圾斗放到粗略整理層,抹布涂料放到中度整理層,盆栽放到最終效果層。這里TCP/IP也對(duì)OSI的網(wǎng)絡(luò)模型層進(jìn)行了劃分:大致如下:

OSI模型:


TCP/IP協(xié)議參考模型把所有的TCP/IP系列協(xié)議歸類到四個(gè)抽象層中

應(yīng)用層:TFTP,HTTP,SNMP,F(xiàn)TP,SMTP,DNS,Telnet 等等

傳輸層:TCP,UDP

網(wǎng)絡(luò)層:IP,ICMP,OSPF,EIGRP,IGMP

數(shù)據(jù)鏈路層:SLIP,CSLIP,PPP,MTU

每一抽象層建立在低一層提供的服務(wù)上,并且為高一層提供服務(wù),看起來(lái)大概是這樣子的


通過(guò)上面的圖形,由于底一層的需要向高一層的提供服務(wù),我們大致的理解應(yīng)用程序需要傳輸層的tcp和網(wǎng)絡(luò)層的ip協(xié)議提供服務(wù),但是我們這章要分析的socket它是在tcpip協(xié)議的那一部分呢,就好比,我們的通訊線路已經(jīng)有明確的規(guī)定,我們的驛站要設(shè)計(jì)在哪個(gè)地方一樣

3:回過(guò)頭再來(lái)理解socket

     到目前為止,大致的了解了應(yīng)用程序和tcpip協(xié)議的大致關(guān)系,我們只是知道socket編程是在tcp/IP上的網(wǎng)絡(luò)編程,但是socket在上述的模型的什么位置呢。這個(gè)位置被一個(gè)天才的理論家或者是抽象的計(jì)算機(jī)大神提出并且安排出來(lái)


我們可以發(fā)現(xiàn)socket就在應(yīng)用程序的傳輸層和應(yīng)用層之間,設(shè)計(jì)了一個(gè)socket抽象層,傳輸層的底一層的服務(wù)提供給socket抽象層,socket抽象層再提供給應(yīng)用層,問(wèn)題又來(lái)了,應(yīng)用層和socket抽象層之間和傳輸層,網(wǎng)絡(luò)層之間如何通訊的呢,了解這個(gè)之前,我們還是回到原點(diǎn)

   要想理解socket編程怎么通過(guò)socket關(guān)鍵詞實(shí)現(xiàn)服務(wù)器和客戶端通訊,必須得實(shí)現(xiàn)的了解tcp/ip是怎么通訊的,在這個(gè)的基礎(chǔ)上在去理解socket的握手通訊

    在tcp/ip協(xié)議中,tcp通過(guò)三次握手建立起一個(gè)tcp的鏈接,大致如下

    第一次握手:客戶端嘗試連接服務(wù)器,向服務(wù)器發(fā)送syn包,syn=j,客戶端進(jìn)入SYN_SEND狀態(tài)等待服務(wù)器確認(rèn)

    第二次握手:服務(wù)器接收客戶端syn包并確認(rèn)(ack=j+1),同時(shí)向客戶端發(fā)送一個(gè)SYN包(syn=k),即SYN+ACK包,此時(shí)服務(wù)器進(jìn)入SYN_RECV狀態(tài)

    第三次握手:客戶端收到服務(wù)器的SYN+ACK包,向服務(wù)器發(fā)送確認(rèn)包ACK(ack=k+1),此包發(fā)送完畢,客戶端和服務(wù)器進(jìn)入ESTABLISHED狀態(tài),完成三次握手

    三次握手如下圖:

     根據(jù)tcp的三次握手,socket也定義了三次握手,也許是參考tcp的三次握手,一些計(jì)算機(jī)大神們畫出了socket的三次握手的模型圖

     模型圖如下:

 

     在上面圖的基礎(chǔ)上,如果我們得到上面的圖形,需要我們自己開發(fā)一些接口,來(lái)滿足上面的通訊的三次握手,問(wèn)題就出來(lái)了,我們會(huì)需要開發(fā)哪些函數(shù)

4:socket的一些接口函數(shù)原理

      通過(guò)上面的圖,我們清楚,我們好比一些泛型的程序員,一些理論提供者提供給了我們上面的圖形的理論,我們需要做的就是講上面的圖形的抽象化的東西具體化

      第一次握手:客戶端需要發(fā)送一個(gè)syn j 包,試著去鏈接服務(wù)器端,于是客戶端我們需要提供一個(gè)鏈接函數(shù)

      第二次握手:服務(wù)器端需要接收客戶端發(fā)送過(guò)來(lái)的syn J+1 包,然后在發(fā)送ack包,所以我們需要有服務(wù)器端接受處理函數(shù)

      第三次握手:客戶端的處理函數(shù)和服務(wù)器端的處理函數(shù)

      三次握手只是一個(gè)數(shù)據(jù)傳輸?shù)倪^(guò)程,但是,我們傳輸前需要一些準(zhǔn)備工作,比如將創(chuàng)建一個(gè)套接字,收集一些計(jì)算機(jī)的資源,將一些資源綁定套接字里面,以及接受和發(fā)送數(shù)據(jù)的函數(shù)等等,這些功能接口在一起構(gòu)成了socket的編程

     下面大致的按照客戶端和服務(wù)端將所需的函數(shù)詳細(xì)的列舉出來(lái)


上面的兩個(gè)圖都概述了socket的通訊原理

5:socket的一個(gè)例子,總結(jié)上述的問(wèn)題

詳細(xì)就不在說(shuō)明,通過(guò)一段代碼詳細(xì)的解釋

客戶端的代碼:

#include <winsock2.h>                
#include <stdio.h>  
#pragma comment(lib,"ws2_32.lib")  
int main()  
{  
    //SOCKET前的一些檢查,檢查協(xié)議庫(kù)的版本,為了避免別的版本的socket,并且通過(guò)  
    //WSAStartup啟動(dòng)對(duì)應(yīng)的版本,WSAStartup的參數(shù)一個(gè)是版本信息,一個(gè)是一些詳細(xì)的細(xì)節(jié),注意高低位  
    //WSAStartup與WSACleanup對(duì)應(yīng)  
    int err;  
    WORD versionRequired;  
    WSADATA wsaData;  
    versionRequired=MAKEWORD(1,1);       
    err=WSAStartup(versionRequired,&wsaData);//協(xié)議庫(kù)的版本信息  
  
    //通過(guò)WSACleanup的返回值來(lái)確定socket協(xié)議是否啟動(dòng)  
    if (!err)  
    {  
        printf("客戶端嵌套字已經(jīng)打開!\n");  
    }  
    else  
    {  
        printf("客戶端的嵌套字打開失敗!\n");  
        return 0;//結(jié)束  
    }  
    //創(chuàng)建socket這個(gè)關(guān)鍵詞,這里想一下那個(gè)圖形中的socket抽象層  
    //注意socket這個(gè)函數(shù),他三個(gè)參數(shù)定義了socket的所處的系統(tǒng),socket的類型,以及一些其他信息  
    SOCKET clientSocket=socket(AF_INET,SOCK_STREAM,0);  
  
    //socket編程中,它定義了一個(gè)結(jié)構(gòu)體SOCKADDR_IN來(lái)存計(jì)算機(jī)的一些信息,像socket的系統(tǒng),  
    //端口號(hào),ip地址等信息,這里存儲(chǔ)的是服務(wù)器端的計(jì)算機(jī)的信息  
    SOCKADDR_IN clientsock_in;  
    clientsock_in.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");  
    clientsock_in.sin_family=AF_INET;  
    clientsock_in.sin_port=htons(6000);  
  
    //前期定義了套接字,定義了服務(wù)器端的計(jì)算機(jī)的一些信息存儲(chǔ)在clientsock_in中,  
    //準(zhǔn)備工作完成后,然后開始將這個(gè)套接字鏈接到遠(yuǎn)程的計(jì)算機(jī)  
    //也就是第一次握手  
  
    connect(clientSocket,(SOCKADDR*)&clientsock_in,sizeof(SOCKADDR));//開始連接  
  
  
    char receiveBuf[100];  
  
    //解釋socket里面的內(nèi)容  
    recv(clientSocket,receiveBuf,101,0);  
    printf("%s\n",receiveBuf);  
  
    //發(fā)送socket數(shù)據(jù)  
    send(clientSocket,"hello,this is client",strlen("hello,this is client")+1,0);  
  
    //關(guān)閉套接字  
    closesocket(clientSocket);  
    //關(guān)閉服務(wù)  
    WSACleanup();  
    return 0;  
}

對(duì)應(yīng)服務(wù)端的代碼

#include <winsock2.h>  
#include <stdio.h>  
#pragma comment(lib,"ws2_32.lib")  
int main()  
{  
       //創(chuàng)建套接字,socket前的一些檢查工作,包括服務(wù)的啟動(dòng)  
       WORD myVersionRequest;  
       WSADATA wsaData;  
       myVersionRequest=MAKEWORD(1,1);  
       int err;  
       err=WSAStartup(myVersionRequest,&wsaData);  
       if (!err)  
       {  
              printf("已打開套接字\n");              
       }  
       else  
       {  
              //進(jìn)一步綁定套接字  
              printf("嵌套字未打開!");  
              return 0;  
       }  
       SOCKET serSocket=socket(AF_INET,SOCK_STREAM,0);//創(chuàng)建了可識(shí)別套接字  
       //需要綁定的參數(shù),主要是本地的socket的一些信息。  
       SOCKADDR_IN addr;  
       addr.sin_family=AF_INET;  
       addr.sin_addr.S_un.S_addr=htonl(INADDR_ANY);//ip地址  
       addr.sin_port=htons(6000);//綁定端口  
  
       bind(serSocket,(SOCKADDR*)&addr,sizeof(SOCKADDR));//綁定完成  
       listen(serSocket,5);//其中第二個(gè)參數(shù)代表能夠接收的最多的連接數(shù)  
  
       SOCKADDR_IN clientsocket;  
       int len=sizeof(SOCKADDR);  
       while (1)  
       {  
          //第二次握手,通過(guò)accept來(lái)接受對(duì)方的套接字的信息  
              SOCKET serConn=accept(serSocket,(SOCKADDR*)&clientsocket,&len);//如果這里不是accept而是conection的話。。就會(huì)不斷的監(jiān)聽  
              char sendBuf[100];  
              sprintf(sendBuf,"welcome %s to bejing",inet_ntoa(clientsocket.sin_addr));//找對(duì)對(duì)應(yīng)的IP并且將這行字打印到那里  
              //發(fā)送信息  
          send(serConn,sendBuf,strlen(sendBuf)+1,0);  
              char receiveBuf[100];//接收  
              recv(serConn,receiveBuf,strlen(receiveBuf)+1,0);  
              printf("%s\n",receiveBuf);  
              closesocket(serConn);//關(guān)閉  
              WSACleanup();//釋放資源的操作  
       }  
       return 0;  
}  

6:上面例子用到的知識(shí)點(diǎn)

(摘抄carter大神文章):

服務(wù)器端:

其過(guò)程是首先服務(wù)器方要先啟動(dòng),并根據(jù)請(qǐng)求提供相應(yīng)服務(wù):

(1)打開一通信通道并告知本地主機(jī),它愿意在某一公認(rèn)地址上的某端口(如FTP的端口可能為21)接收客戶請(qǐng)求;

(2)等待客戶請(qǐng)求到達(dá)該端口;

(3)接收到客戶端的服務(wù)請(qǐng)求時(shí),處理該請(qǐng)求并發(fā)送應(yīng)答信號(hào)。接收到并發(fā)服務(wù)請(qǐng)求,要激活一新進(jìn)程來(lái)處理這個(gè)客戶請(qǐng)求(如UNIX系統(tǒng)中用fork、exec)。新進(jìn)程處理此客戶請(qǐng)求,并不需要對(duì)其它請(qǐng)求作出應(yīng)答。服務(wù)完成后,關(guān)閉此新進(jìn)程與客戶的通信鏈路,并終止。

(4)返回第(2)步,等待另一客戶請(qǐng)求。

(5)關(guān)閉服務(wù)器

客戶端:

(1)打開一通信通道,并連接到服務(wù)器所在主機(jī)的特定端口;

(2)向服務(wù)器發(fā)服務(wù)請(qǐng)求報(bào)文,等待并接收應(yīng)答;繼續(xù)提出請(qǐng)求......

(3)請(qǐng)求結(jié)束后關(guān)閉通信通道并終止。

從上面所描述過(guò)程可知:

(1)客戶與服務(wù)器進(jìn)程的作用是非對(duì)稱的,因此代碼不同。

(2)服務(wù)器進(jìn)程一般是先啟動(dòng)的。只要系統(tǒng)運(yùn)行,該服務(wù)進(jìn)程一直存在,直到正常或強(qiáng)迫終止。

7:下面就介紹一些API函數(shù):

(摘抄carter大神文章):

 創(chuàng)建套接字──socket()

應(yīng)用程序在使用套接字前,首先必須擁有一個(gè)套接字,系統(tǒng)調(diào)用socket()向應(yīng)用程序提供創(chuàng)建套接字的手段,其調(diào)用格式如下:

SOCKET PASCAL FAR socket(int af, int type, int protocol)

該調(diào)用要接收三個(gè)參數(shù):af、type、protocol。參數(shù)af指定通信發(fā)生的區(qū)域:AF_UNIX、AF_INET、AF_NS等,而DOS、WINDOWS中僅支持AF_INET,它是網(wǎng)際網(wǎng)區(qū)域。因此,地址族與協(xié)議族相同。參數(shù)type 描述要建立的套接字的類型。這里分三種:

(1)一是TCP流式套接字(SOCK_STREAM)提供了一個(gè)面向連接、可靠的數(shù)據(jù)傳輸服務(wù),數(shù)據(jù)無(wú)差錯(cuò)、無(wú)重復(fù)地發(fā)送,且按發(fā)送順序接收。內(nèi)設(shè)流量控制,避免數(shù)據(jù)流超限;數(shù)據(jù)被看作是字節(jié)流,無(wú)長(zhǎng)度限制。文件傳送協(xié)議(FTP)即使用流式套接字。

(2)二是數(shù)據(jù)報(bào)式套接字(SOCK_DGRAM)提供了一個(gè)無(wú)連接服務(wù)。數(shù)據(jù)包以獨(dú)立包形式被發(fā)送,不提供無(wú)錯(cuò)保證,數(shù)據(jù)可能丟失或重復(fù),并且接收順序混亂。網(wǎng)絡(luò)文件系統(tǒng)(NFS)使用數(shù)據(jù)報(bào)式套接字。

(3)三是原始式套接字(SOCK_RAW)該接口允許對(duì)較低層協(xié)議,如IP、ICMP直接訪問(wèn)。常用于檢驗(yàn)新的協(xié)議實(shí)現(xiàn)或訪問(wèn)現(xiàn)有服務(wù)中配置的新設(shè)備。

參數(shù)protocol說(shuō)明該套接字使用的特定協(xié)議,如果調(diào)用者不希望特別指定使用的協(xié)議,則置為0,使用默認(rèn)的連接模式。根據(jù)這三個(gè)參數(shù)建立一個(gè)套接字,并將相應(yīng)的資源分配給它,同時(shí)返回一個(gè)整型套接字號(hào)。因此,socket()系統(tǒng)調(diào)用實(shí)際上指定了相關(guān)五元組中的“協(xié)議”這一元。

指定本地地址──bind()

當(dāng)一個(gè)套接字用socket()創(chuàng)建后,存在一個(gè)名字空間(地址族),但它沒(méi)有被命名。bind()將套接字地址(包括本地主機(jī)地址和本地端口地址)與所創(chuàng)建的套接字號(hào)聯(lián)系起來(lái),即將名字賦予套接字,以指定本地半相關(guān)。其調(diào)用格式如下:

int PASCAL FAR bind(SOCKET s, const struct sockaddr FAR * name, int namelen);

參數(shù)s是由socket()調(diào)用返回的并且未作連接的套接字描述符(套接字號(hào))。參數(shù)name 是賦給套接字s的本地地址(名字),其長(zhǎng)度可變,結(jié)構(gòu)隨通信域的不同而不同。namelen表明了name的長(zhǎng)度。如果沒(méi)有錯(cuò)誤發(fā)生,bind()返回0。否則返回SOCKET_ERROR。

建立套接字連接──connect()與accept()

這兩個(gè)系統(tǒng)調(diào)用用于完成一個(gè)完整相關(guān)的建立,其中connect()用于建立連接。accept()用于使服務(wù)器等待來(lái)自某客戶進(jìn)程的實(shí)際連接。

connect()的調(diào)用格式如下:

int PASCAL FAR connect(SOCKET s, const struct sockaddr FAR * name, int namelen);

參數(shù)s是欲建立連接的本地套接字描述符。參數(shù)name指出說(shuō)明對(duì)方套接字地址結(jié)構(gòu)的指針。對(duì)方套接字地址長(zhǎng)度由namelen說(shuō)明。

如果沒(méi)有錯(cuò)誤發(fā)生,connect()返回0。否則返回值SOCKET_ERROR。在面向連接的協(xié)議中,該調(diào)用導(dǎo)致本地系統(tǒng)和外部系統(tǒng)之間連接實(shí)際建立。

由于地址族總被包含在套接字地址結(jié)構(gòu)的前兩個(gè)字節(jié)中,并通過(guò)socket()調(diào)用與某個(gè)協(xié)議族相關(guān)。因此bind()和connect()無(wú)須協(xié)議作為參數(shù)。

accept()的調(diào)用格式如下:

SOCKET PASCAL FAR accept(SOCKET s, struct sockaddr FAR* addr, int FAR* addrlen);

參數(shù)s為本地套接字描述符,在用做accept()調(diào)用的參數(shù)前應(yīng)該先調(diào)用過(guò)listen()。addr 指向客戶方套接字地址結(jié)構(gòu)的指針,用來(lái)接收連接實(shí)體的地址。addr的確切格式由套接字創(chuàng)建時(shí)建立的地址族決定。addrlen 為客戶方套接字地址的長(zhǎng)度(字節(jié)數(shù))。如果沒(méi)有錯(cuò)誤發(fā)生,accept()返回一個(gè)SOCKET類型的值,表示接收到的套接字的描述符。否則返回值INVALID_SOCKET。

accept()用于面向連接服務(wù)器。參數(shù)addr和addrlen存放客戶方的地址信息。調(diào)用前,參數(shù)addr 指向一個(gè)初始值為空的地址結(jié)構(gòu),而addrlen 的初始值為0;調(diào)用accept()后,服務(wù)器等待從編號(hào)為s的套接字上接受客戶連接請(qǐng)求,而連接請(qǐng)求是由客戶方的connect()調(diào)用發(fā)出的。當(dāng)有連接請(qǐng)求到達(dá)時(shí),accept()調(diào)用將請(qǐng)求連接隊(duì)列上的第一個(gè)客戶方套接字地址及長(zhǎng)度放入addr 和addrlen,并創(chuàng)建一個(gè)與s有相同特性的新套接字號(hào)。新的套接字可用于處理服務(wù)器并發(fā)請(qǐng)求。

四個(gè)套接字系統(tǒng)調(diào)用,socket()、bind()、connect()、accept(),可以完成一個(gè)完全五元相關(guān)的建立。socket()指定五元組中的協(xié)議元,它的用法與是否為客戶或服務(wù)器、是否面向連接無(wú)關(guān)。bind()指定五元組中的本地二元,即本地主機(jī)地址和端口號(hào),其用法與是否面向連接有關(guān):在服務(wù)器方,無(wú)論是否面向連接,均要調(diào)用bind(),若采用面向連接,則可以不調(diào)用bind(),而通過(guò)connect()自動(dòng)完成。若采用無(wú)連接,客戶方必須使用bind()以獲得一個(gè)唯一的地址。

監(jiān)聽連接──listen()

此調(diào)用用于面向連接服務(wù)器,表明它愿意接收連接。listen()需在accept()之前調(diào)用,其調(diào)用格式如下:

int PASCAL FAR listen(SOCKET s, int backlog);

參數(shù)s標(biāo)識(shí)一個(gè)本地已建立、尚未連接的套接字號(hào),服務(wù)器愿意從它上面接收請(qǐng)求。backlog表示請(qǐng)求連接隊(duì)列的最大長(zhǎng)度,用于限制排隊(duì)請(qǐng)求的個(gè)數(shù),目前允許的最大值為5。如果沒(méi)有錯(cuò)誤發(fā)生,listen()返回0。否則它返回SOCKET_ERROR。

listen()在執(zhí)行調(diào)用過(guò)程中可為沒(méi)有調(diào)用過(guò)bind()的套接字s完成所必須的連接,并建立長(zhǎng)度為backlog的請(qǐng)求連接隊(duì)列。

調(diào)用listen()是服務(wù)器接收一個(gè)連接請(qǐng)求的四個(gè)步驟中的第三步。它在調(diào)用socket()分配一個(gè)流套接字,且調(diào)用bind()給s賦于一個(gè)名字之后調(diào)用,而且一定要在accept()之前調(diào)用。

數(shù)據(jù)傳輸──send()與recv()

當(dāng)一個(gè)連接建立以后,就可以傳輸數(shù)據(jù)了。常用的系統(tǒng)調(diào)用有send()和recv()。

send()調(diào)用用于s指定的已連接的數(shù)據(jù)報(bào)或流套接字上發(fā)送輸出數(shù)據(jù),格式如下:

int PASCAL FAR send(SOCKET s, const char FAR *buf, int len, int flags);

參數(shù)s為已連接的本地套接字描述符。buf 指向存有發(fā)送數(shù)據(jù)的緩沖區(qū)的指針,其長(zhǎng)度由len 指定。flags 指定傳輸控制方式,如是否發(fā)送帶外數(shù)據(jù)等。如果沒(méi)有錯(cuò)誤發(fā)生,send()返回總共發(fā)送的字節(jié)數(shù)。否則它返回SOCKET_ERROR。

recv()調(diào)用用于s指定的已連接的數(shù)據(jù)報(bào)或流套接字上接收輸入數(shù)據(jù),格式如下:

int PASCAL FAR recv(SOCKET s, char FAR *buf, int len, int flags);

參數(shù)s 為已連接的套接字描述符。buf指向接收輸入數(shù)據(jù)緩沖區(qū)的指針,其長(zhǎng)度由len 指定。flags 指定傳輸控制方式,如是否接收帶外數(shù)據(jù)等。如果沒(méi)有錯(cuò)誤發(fā)生,recv()返回總共接收的字節(jié)數(shù)。如果連接被關(guān)閉,返回0。否則它返回SOCKET_ERROR。

輸入/輸出多路復(fù)用──select()

select()調(diào)用用來(lái)檢測(cè)一個(gè)或多個(gè)套接字的狀態(tài)。對(duì)每一個(gè)套接字來(lái)說(shuō),這個(gè)調(diào)用可以請(qǐng)求讀、寫或錯(cuò)誤狀態(tài)方面的信息。請(qǐng)求給定狀態(tài)的套接字集合由一個(gè)fd_set結(jié)構(gòu)指示。在返回時(shí),此結(jié)構(gòu)被更新,以反映那些滿足特定條件的套接字的子集,同時(shí), select()調(diào)用返回滿足條件的套接字的數(shù)目,其調(diào)用格式如下:

int PASCAL FAR select(int nfds, fd_set FAR * readfds, fd_set FAR * writefds, fd_set FAR * exceptfds, const struct timeval FAR * timeout);

參數(shù)nfds指明被檢查的套接字描述符的值域,此變量一般被忽略。

參數(shù)readfds指向要做讀檢測(cè)的套接字描述符集合的指針,調(diào)用者希望從中讀取數(shù)據(jù)。參數(shù)writefds 指向要做寫檢測(cè)的套接字描述符集合的指針。exceptfds指向要檢測(cè)是否出錯(cuò)的套接字描述符集合的指針。timeout指向select()函數(shù)等待的最大時(shí)間,如果設(shè)為NULL則為阻塞操作。select()返回包含在fd_set結(jié)構(gòu)中已準(zhǔn)備好的套接字描述符的總數(shù)目,或者是發(fā)生錯(cuò)誤則返回SOCKET_ERROR。

關(guān)閉套接字──closesocket()

closesocket()關(guān)閉套接字s,并釋放分配給該套接字的資源;如果s涉及一個(gè)打開的TCP連接,則該連接被釋放。closesocket()的調(diào)用格式如下:

BOOL PASCAL FAR closesocket(SOCKET s);

參數(shù)s待關(guān)閉的套接字描述符。如果沒(méi)有錯(cuò)誤發(fā)生,closesocket()返回0。否則返回值SOCKET_ERROR。

以上就是socket編程的詳細(xì)講解的詳細(xì)內(nèi)容,更多關(guān)于socket編程的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Opencv檢測(cè)多個(gè)圓形(霍夫圓檢測(cè),輪廓面積篩選)

    Opencv檢測(cè)多個(gè)圓形(霍夫圓檢測(cè),輪廓面積篩選)

    本文主要介紹了Opencv檢測(cè)多個(gè)圓形(霍夫圓檢測(cè),輪廓面積篩選),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • C語(yǔ)言數(shù)據(jù)結(jié)構(gòu) 棧的基礎(chǔ)操作

    C語(yǔ)言數(shù)據(jù)結(jié)構(gòu) 棧的基礎(chǔ)操作

    這篇文章主要介紹了C語(yǔ)言數(shù)據(jù)結(jié)構(gòu) 棧的基礎(chǔ)操作的相關(guān)資料,需要的朋友可以參考下
    2017-05-05
  • ubuntu中打開終端的三種解決方法

    ubuntu中打開終端的三種解決方法

    本篇文章是對(duì)ubuntu中打開終端的三種方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • 詳解c++優(yōu)先隊(duì)列priority_queue的用法

    詳解c++優(yōu)先隊(duì)列priority_queue的用法

    本文詳細(xì)講解了c++優(yōu)先隊(duì)列priority_queue的用法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-12-12
  • 如何基于C語(yǔ)言socket編程實(shí)現(xiàn)TCP通信

    如何基于C語(yǔ)言socket編程實(shí)現(xiàn)TCP通信

    本文介紹了如何基于C語(yǔ)言socket編程實(shí)現(xiàn)TCP通信,下面小編來(lái)簡(jiǎn)單介紹下
    2019-05-05
  • C語(yǔ)言的結(jié)構(gòu)體你了解嗎

    C語(yǔ)言的結(jié)構(gòu)體你了解嗎

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言的結(jié)構(gòu)體,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-02-02
  • C語(yǔ)言strlen函數(shù)全方位講解

    C語(yǔ)言strlen函數(shù)全方位講解

    在C語(yǔ)言中我們要獲取字符串的長(zhǎng)度,可以使用strlen函數(shù),strlen函數(shù)計(jì)算字符串的長(zhǎng)度時(shí),直到空結(jié)束字符,但不包括空結(jié)束字符,因?yàn)?nbsp;strlen函數(shù)時(shí)不包含最后的結(jié)束字符的,因此一般使用strlen函數(shù)計(jì)算的字符串的長(zhǎng)度會(huì)比使用sizeof計(jì)算的字符串的字節(jié)數(shù)要小
    2022-09-09
  • C語(yǔ)言中動(dòng)態(tài)內(nèi)存管理初學(xué)者容易犯的6個(gè)錯(cuò)誤分享

    C語(yǔ)言中動(dòng)態(tài)內(nèi)存管理初學(xué)者容易犯的6個(gè)錯(cuò)誤分享

    本篇文章主要介紹了初學(xué)者使用C語(yǔ)言中動(dòng)態(tài)內(nèi)存管理的4個(gè)函數(shù)時(shí)最容易犯的6個(gè)錯(cuò)誤,以及如何避免這些錯(cuò)誤,文中的示例代碼講解詳細(xì),感興趣的可以了解一下
    2023-04-04
  • C語(yǔ)言二維數(shù)組應(yīng)用之掃雷游戲

    C語(yǔ)言二維數(shù)組應(yīng)用之掃雷游戲

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言二維數(shù)組應(yīng)用之掃雷游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • 詳解c++中的類型識(shí)別

    詳解c++中的類型識(shí)別

    這篇文章主要介紹了 詳解c++中的類型識(shí)別,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06

最新評(píng)論