日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

Socket 之 API函数介绍

發(fā)布時間:2023/12/13 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Socket 之 API函数介绍 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

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

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

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

  該調(diào)用要接收三個參數(shù):af、type、protocol。

  (1)af:指定通信發(fā)生的區(qū)域:AF_UNIX、AF_INET、AF_NS等,而DOS、WINDOWS中僅支持AF_INET,它是網(wǎng)際網(wǎng)區(qū)域。因此,地址族與協(xié)議族相同。

  (2)type:描述要建立的套接字的類型。這里分三種:

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

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

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

  (3)protocol:說明該套接字使用的特定協(xié)議,如果調(diào)用者不希望特別指定使用的協(xié)議,則置為0,使用默認的連接模式。

  根據(jù)這三個參數(shù)建立一個套接字,并將相應(yīng)的資源分配給它,同時返回一個整型套接字號。因此,socket()系統(tǒng)調(diào)用實際上指定了相關(guān)五元組中的“協(xié)議”這一元。

?

2、指定本地地址──bind()

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

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

  (1)s:是由socket()調(diào)用返回的并且未作連接的套接字描述符(套接字號)。

  (2)name:是賦給套接字s的本地地址(名字),其長度可變,結(jié)構(gòu)隨通信域的不同而不同。

  (3)namelen:表明了name的長度。

  如果沒有錯誤發(fā)生,bind()返回0。否則返回SOCKET_ERROR。

?

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

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

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

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

  參數(shù)s是欲建立連接的本地套接字描述符。

  參數(shù)name指出說明對方套接字地址結(jié)構(gòu)的指針。

  對方套接字地址長度由namelen說明。

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

  由于地址簇總被包含在套接字地址結(jié)構(gòu)的前兩個字節(jié)中,并通過socket()調(diào)用與某個協(xié)議簇相關(guān)。因此bind()和connect()無須協(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)用過listen()。

  addr 指向客戶方套接字地址結(jié)構(gòu)的指針,用來接收連接實體的地址。addr的確切格式由套接字創(chuàng)建時建立的地址族決定。

  addrlen 為客戶方套接字地址的長度(字節(jié)數(shù))。

  如果沒有錯誤發(fā)生,accept()返回一個SOCKET類型的值,表示接收到的套接字的描述符。否則返回值INVALID_SOCKET。

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

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

?

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

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

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

  參數(shù)s標識一個本地已建立、尚未連接的套接字號,服務(wù)器愿意從它上面接收請求。

  backlog表示請求連接隊列的最大長度,用于限制排隊請求的個數(shù),目前允許的最大值為5。

  如果沒有錯誤發(fā)生,listen()返回0。否則它返回SOCKET_ERROR。

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

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

?

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

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

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

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

  參數(shù)s為已連接的本地套接字描述符。

  buf 指向存有發(fā)送數(shù)據(jù)的緩沖區(qū)的指針,其長度由len 指定。

  flags 指定傳輸控制方式,如是否發(fā)送帶外數(shù)據(jù)等。

  如果沒有錯誤發(fā)生,send()返回總共發(fā)送的字節(jié)數(shù)。否則它返回SOCKET_ERROR。

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

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

  參數(shù)s 為已連接的套接字描述符。

  buf指向接收輸入數(shù)據(jù)緩沖區(qū)的指針,

  其長度由len 指定。

  flags 指定傳輸控制方式,如是否接收帶外數(shù)據(jù)等。

  如果沒有錯誤發(fā)生,recv()返回總共接收的字節(jié)數(shù)。如果連接被關(guān)閉,返回0。否則它返回SOCKET_ERROR。

?

6、輸入/輸出多路復用──select()

  select()調(diào)用用來檢測一個或多個套接字的狀態(tài)。對每一個套接字來說,這個調(diào)用可以請求讀、寫或錯誤狀態(tài)方面的信息。請求給定狀態(tài)的套接字集合由一個fd_set結(jié)構(gòu)指示。在返回時,此結(jié)構(gòu)被更新,以反映那些滿足特定條件的套接字的子集,同時, 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指向要做讀檢測的套接字描述符集合的指針,調(diào)用者希望從中讀取數(shù)據(jù)。

  參數(shù)writefds 指向要做寫檢測的套接字描述符集合的指針。

  exceptfds指向要檢測是否出錯的套接字描述符集合的指針。

  timeout指向select()函數(shù)等待的最大時間,如果設(shè)為NULL則為阻塞操作。

  select()返回包含在fd_set結(jié)構(gòu)中已準備好的套接字描述符的總數(shù)目,或者是發(fā)生錯誤則返回SOCKET_ERROR。

?

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

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

  BOOL PASCAL FAR closesocket(SOCKET s);

  參數(shù)s待關(guān)閉的套接字描述符。

  如果沒有錯誤發(fā)生,closesocket()返回0。否則返回值SOCKET_ERROR。

?

以上就是SOCKET API一些常用的API函數(shù),下面是一段代碼:

?

//客戶端代碼:

#include <WINSOCK2.H>

#include <stdio.h>

#pragma comment(lib,"ws2_32.lib")

?

int main()

{

?????? int err;

?????? WORD versionRequired;

?????? WSADATA wsaData;

?????? versionRequired=MAKEWORD(1,1);

?????? err=WSAStartup(versionRequired,&wsaData);//協(xié)議庫的版本信息

??????

?????? if (!err)

?????? {

????????????? printf("客戶端嵌套字已經(jīng)打開!\n");

?????? }

?????? else

?????? {

????????????? printf("客戶端的嵌套字打開失敗!\n");

????????????? return 0;//結(jié)束

?????? }

?????? SOCKET clientSocket=socket(AF_INET,SOCK_STREAM,0);

?????? 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);

?????? //bind(clientSocket,(SOCKADDR*)&clientsock_in,strlen(SOCKADDR));//注意第三個參數(shù)

?????? //listen(clientSocket,5);

?????? connect(clientSocket,(SOCKADDR*)&clientsock_in,sizeof(SOCKADDR));//開始連接

??????

?????? char receiveBuf[100];

?????? recv(clientSocket,receiveBuf,101,0);

?????? printf("%s\n",receiveBuf);

??????

?????? send(clientSocket,"hello,this is client",strlen("hello,this is client")+1,0);

?????? closesocket(clientSocket);

?????? WSACleanup();

?????? return 0;

}

?

///

//服務(wù)器端代碼:

#include <WINSOCK2.H>

#include <stdio.h>

#pragma comment(lib,"ws2_32.lib")

int main()

{

?????? //創(chuàng)建套接字

?????? WORD myVersionRequest;

?????? WSADATA wsaData;

?????? myVersionRequest=MAKEWORD(1,1);

?????? int err;

?????? err=WSAStartup(myVersionRequest,&wsaData);

?????? if (!err)

?????? {

????????????? printf("已打開套接字\n");

?????????????

?????? }

?????? else

?????? {

????????????? //進一步綁定套接字

????????????? printf("嵌套字未打開!");

????????????? return 0;

?????? }

?????? SOCKET serSocket=socket(AF_INET,SOCK_STREAM,0);//創(chuàng)建了可識別套接字

?????? //需要綁定的參數(shù)

?????? 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);//其中第二個參數(shù)代表能夠接收的最多的連接數(shù)

??????

?????? //

?????? //開始進行監(jiān)聽

?????? //

?????? SOCKADDR_IN clientsocket;

?????? int len=sizeof(SOCKADDR);

?????? while (1)

?????? {

????????????? SOCKET serConn=accept(serSocket,(SOCKADDR*)&clientsocket,&len);//如果這里不是accept而是conection的話。。就會不斷的監(jiān)聽

????????????? char sendBuf[100];

?????????????

????????????? sprintf(sendBuf,"welcome %s to bejing",inet_ntoa(clientsocket.sin_addr));//找對對應(yīng)的IP并且將這行字打印到那里

????????????? 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;

}

轉(zhuǎn)載于:https://www.cnblogs.com/xinaixia/p/5460557.html

總結(jié)

以上是生活随笔為你收集整理的Socket 之 API函数介绍的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。