1. 程式人生 > 實用技巧 >網路程式設計 C++ 基礎函式

網路程式設計 C++ 基礎函式

一.網路程式設計的基本過程(windows)


1.呼叫socket函式建立套接字

 2.呼叫bind函式分配IP地址和埠號

 3.呼叫listen函式轉為可接收請求。

4.呼叫accept函式受理連線請求。

5.資料的傳送和接收

6.客戶端的請求連線

7.關閉套接字

 

1.建立套接字

socket(int af,int type,int protocol);        //成功返回套接字控制代碼,失敗返回INVALID_SOCKET

af為協議族:PF_INET 為ipv4網際網路協議族,PF_INET6為IPv6網際網路協議族。目前普遍使用ipv4。
type為:面向連線的套接字(SOCK_STREAM),面向訊息的套接字(SOCK_DGRAM)。
一般情況下protocol可以傳遞0,除非遇到同一協議族中存在多個數據傳輸方式相同的協議。例如:TCP協議IPPROTO_TCP ,UDP協議為IPPROTO_UDP。

2.進行繫結

bind(SOCKET s,struct sockaddr *name,int addrlen);     //成功返回0,失敗返回SOCKET_ERROR

addrlen:佔記憶體大小,一般使用sizeof(name)

name:指向含有本機IP地址及埠號的sockaddr型別的指標

struct sockaddr_in{

sa_family_t sin_family; //地址族 IPV4:AF_INET IPV6:AF_INET6
uint16_t sin_port; //16位埠號 ,它以網路位元組序儲存
struct in_addr sin_addr; //32位IP地址 它以網路位元組序儲存
char sin_zero[8]; //不使用 必須填充為0
}
其中
struct in_addr
{
In_addr_t s_addr; ///32位IPV4地址。
}

可分配的埠號為:0~65535,其中0~1023是知名埠不可以使用。

注意sin_portsin_addr需要轉換成網路位元組序
位元組序轉換:htons(unsigned short);其中h代表主機位元組序,n代表網路位元組序,s指的是short,l指的是long,中間用to連線。可以理解為把short型的資料從主機位元組序轉化為網路位元組序。

將字串資訊轉為網路位元組序的整數型:
inet_addr(const char * string);成功返回32為大端序整數型值,失敗時返回INADDR_NONE.還可以檢測是否為合理ip地址。
inet_aton函式與inet_addr在功能上完全相同。只是inet_aton利用了in_addr結構體,且其使用頻率更高。
inet_ntoa(struct in_addr adr)相反,成功時返回轉換後的字串地址值,失敗返回-1;


※ 每次建立伺服器端套接字都要輸入IP地址會有些繁瑣,可以使用INADDR_ANY,如:addr.sin_addr.s_addr=htonl(INADDR_ANY).

※ 普遍使用memset()函式,主要作用是使sockaddr_in結構體中的sin_zero為0。

3.進行監聽

listen(SOCKET s,int backlog);     // 成功返回0,失敗返回SOCKET_ERROR

s 為需要進入監聽狀態的套接字

backlog 為請求佇列的最大長度。

當套接字正在處理客戶端請求時,如果有新的請求進來,套接字是沒法處理的,只能把它放進緩衝區,待當前請求處理完畢後,再從緩衝區中讀取出來處理。如果不斷有新的請求進來,它們就按照先後順序在緩衝區中排隊,直到緩衝區滿。這個緩衝區,就稱為請求佇列(Request Queue)。

緩衝區的長度(能存放多少個客戶端請求)可以通過 listen() 函式的 backlog 引數指定,但究竟為多少並沒有什麼標準,可以根據你的需求來定,併發量小的話可以是10或者20。

如果將 backlog 的值設定為 SOMAXCONN,就由系統來決定請求佇列長度,這個值一般比較大,可能是幾百,或者更多。

當請求佇列滿時,就不再接收新的請求,對於 Linux,客戶端會收到 ECONNREFUSED 錯誤,對於 Windows,客戶端會收到 WSAECONNREFUSED 錯誤。

listen() 只是讓套接字處於監聽狀態,並沒有接收請求。


4.接收

accept(SOCKET s,struct sockaddr *addr,int *addrlen);   // 成功返回套接字控制代碼,失敗返回INVALID_SOCKET

它的引數與 listen() 和 connect() 是相同的。

s為伺服器端套接字

addr 為 sockaddr_in 結構體變數

addrlen 為引數 addr 的長度,可由 sizeof() 求得。

accept()返回一個新的套接字來和客服端通訊,addr儲存了客戶端的IP地址和埠號,而s是伺服器端的套接字。後面和客戶端通訊時,要使用這個新生成的套接字,而不是原來伺服器端的套接字。

listen() 只是讓套接字進入監聽狀態,並沒有真正接收客戶端請求,listen() 後面的程式碼會繼續執行,直到遇到 accept()。accept() 會阻塞程式執行(後面程式碼不能被執行),直到有新的請求到來。

5.資料的接收與傳送

send(SOCKET s,const char * buf,int len,int flags);  //成功時返回傳輸位元組數。失敗時返回SOCKET_ERROR。

其中s 表示資料傳輸物件連線的套接字控制代碼值。

buf 儲存待傳輸資料的緩衝地址值。

len要傳輸的位元組數。

flags傳輸資料時用到的多種選項資訊。一般設定為 0 或 NULL。

recv(SOCKET s,const char * buf,int len,int flags);  //成功時返回接收的位元組數(收到EOF時為0),失敗返回SOCKET_ERROR.

其中s 表示資料接收物件連線的套接字控制代碼值

buf儲存結束資料的緩衝地址值

len表示接收的最大位元組數

flags表示接收資料時用到的多種選項資訊。


6.客戶端的請求連線

connect(SOCKET s,struct sockaddr *serv_addr,int addrlen);  //  成功返回0,失敗返回SOCKET_ERROR

serv_addr 包含遠端主機的IP地址和埠號的指標

addrlen 遠端地址結構的長度

對於客戶端無需像伺服器端一樣使用bind()、listen()、accept()函式。

7.關閉套接字

closesocket(SOCKET s);   //成功返回0 失敗返回SOCKET_ERROR

不管是客戶端還是伺服器端最後都不要忘記使用closesocket()函式關閉建立的套接字。