網路程式設計基礎01 — 這些API要熟悉
1.Linux API
套接字相關:
#include <sys/types.h> #include <sys/socket.h> /* 功能:建立套接字; * 引數:domain - 協議族資訊:PF_INET:IPv4網際網路協議族; * PF_INET6:IPv6網際網路協議族; * PF_LOCAL:本地通訊的UNIX協議族; * PF_PACKET:底層套接字的協議族; * PF_IPX:IPX Novell協議族; * type - 資料傳輸型別:SOCKET_STREAM:位元組流套接字; * SOCKET_DGRAM:資料報套接字; * SOCKET_RAW:原始套接字; * SOOCKET_SEQPACKET:有序分組套接字; * protocol - 協議資訊:IPPROTO_TCP:TCP協議; * IPPROTO_UDP:UDP協議; * IPPROTO_SCTP:SCTP協議; * 返回:成功時返回套接字描述符,失敗時返回-1; */ int socket(int domain, int type, int protocol); /* 功能:將IP地址和埠號繫結到套接字上; * 引數:sockfd - 套接字描述符; * addr - 指向要繫結給sockfd的協議地址; * addrlen - 地址的長度; * 返回:成功時返回0,失敗時返回-1; */ int bind(int sockfd, struct sockaddr *addr, socklen_t addrlen); /* 功能:監聽套接字; * 引數:sockfd - 套接字描述符; * backlog - 連線請求佇列中最大連線個數; * 返回:成功時返回0,失敗時返回-1; */ int listen(int sockfd, int backlog); /* 功能:受理連線請求; * 引數:sockfd - 套接字描述符; * clnt_addr - 客戶端的地址資訊; * addrlen - 客戶端地址長度; * 返回:成功時返回新建立的與當前處理的連線對應的套接字描述符,失敗時返回-1; */ int accept(int sockfd, struct sockaddr *clnt_addr, socklen_t *addrlen); /* 功能:客戶端請求與伺服器建立TCP連線; * 引數:sockfd - 套接字描述符; * serv_addr - 伺服器的地址資訊; * addrlen - 伺服器地址長度; * 返回:成功時返回0,失敗時返回-1; */ int connect(int sockfd, struct sockaddr *serv_addr, socklen_t addrlen);
檔案讀寫相關:
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> /* 功能:開啟檔案; * 引數:path - 檔案全路徑; * flag - 檔案開啟模式; * 返回:成功時返回檔案描述符,失敗時返回-1; */ int open(const char *path, int flag); /* 功能:關閉檔案或套接字; * 引數:fd - 要關閉的檔案或套接字的檔案描述符; * 返回:成功時返回0,失敗時返回-1; */ int close(int fd); /* 功能:寫 * 引數:fd - 檔案/套接字描述符; * buf - 要寫入的資料的起始地址; * nbytes - 要寫入的位元組數; * 返回:成功時返回寫入的位元組數;失敗時返回-1; */ ssize_t write(int fd, const char *buf, size_t nbytes); /* 功能:讀 * 引數:fd - 檔案/套接字描述符; * buf - 要儲存讀取資料的地址; * nbytes - 要讀取資料的最大位元組數; * 返回:成功時返回讀取的位元組數,但遇到檔案結束符返回0;失敗時返回-1; */ ssize_t read(int fd, void *buf, size_t nbytes);
2.sockaddr和sockaddr_in
sockaddr是通用的socket地址,在#include <sys/socket.h>中定義,結構如下:
struct sockaddr
{
unsigned short sa_family;
char sa_data[14];
};
其中:
(1)sa_family表示地址族,長度為2B,形式為"AF_xxx",常用的值有:
AF_INET:IPv4地址資訊;
AF_INET6:IPv6地址資訊;
(2)sa_data表示協議地址資訊,長度為14B;
sockaddr_in在標頭檔案#include<netinet/in.h>或#include <arpa/inet.h>中定義,結構如下:
struct sockaddr_in
{
short int sin_family;
unsigned short int sin_port;
struct in_addr sin_addr;
unsigned char sin_zero[8];
};
其中:
(1)sin_family表示地址族,與sockaddr中的sa_family作用和取值一致;
(2)sin_port表示埠號,必須採用網路位元組序,長度為2B;
(3)sin_addr儲存IP地址,長度為4B;in_addr的結構定義如下:
struct in_addr
{
union {
struct {
u_char s_b1, s_b2, s_b3, s_b4;
} S_un_b;
struct {
u_short s_w1, s_w2;
} S_un_w;
u_long S_addr;
} S_un;
#define s_addr S_un.S_addr
};
(4)sin_zero是為了與struct sockaddr保持大小相同而保留的空位元組,長度為8B;
sockaddr_in將IP地址和埠號分開,方便賦值,網路程式設計中一般使用sockaddr_in定義和賦值,然後再強制轉換為sockaddr作為函式引數。
3.AF_INET與PF_INET
AF:Address Family,設定地址時使用AF_xxx;
PF:Protocol Family,建立socket時是指定協議,因此使用PF_xxx;
TCP/IP設計時認為某個協議族可能有多重形式的地址,即一個PF對應對個AF,因此做了上述區分;
但是實際上目前為止,一個PF只對應1個AF,沒有例外。
實質上,二者是相同的:
#define AF_INET PF_INET
4.Windows API
#include <winsock2.h>
/* 功能:設定winsock版本並初始化相關庫;
* 引數:wVersionRequested - Winsock版本資訊;
* lpWSAData - WSADATA結構體變數的地址;
* 返回:成功時返回0,失敗時返回非零的錯誤碼;
*/
int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData);
/* 功能:解除與socket庫的繫結並釋放系統資源;
* 引數:無;
* 返回:成功時返回0,失敗時返回SOCKET_ERROR;
*/
int WSACleanup(void);
// 返回:成功時返回套接字控制代碼,失敗時返回INVALID_SOCKET;
SOCKET socket(int af, int type, int protocol);
int bind(SOCKET s, const struct sockaddr *name, int namelen);
int listen(SOCKET s, int backlog);
// 成功時返回套接字控制代碼,失敗時返回INVALID_SOCKET;
SOCKET accept(SOCKET s, struct sockaddr *addr, int *addrlen);
// 成功時返回0,失敗時返回SOCKET_ERROR;
int connect(SOCKET s, const struct sockaddr *name, int namelen);
/* 功能:關閉套接字;
* 引數:s - 套接字控制代碼;
* 返回:成功時返回0,失敗時返回SOCKET_ERROR;
*/
int closesocket(SOCKET s);
/* 功能:傳送資料;
* 引數:s - 套接字控制代碼;
* buf - 待傳輸的資料地址;
* len - 要傳輸的位元組數;
* flags - 傳輸選項;
* 返回:成功時返回傳輸的位元組數,失敗時返回SOCKET_ERROR;
*/
int send(SOCKET s, const char *buf, int len, int flags);
/* 功能:接收資料;
* 引數:s - 套接字控制代碼;
* buf - 儲存接收資料的地址;
* len - 可以接收的最大位元組數;
* flags - 傳輸選項;
* 返回:成功時返回傳輸的位元組數,失敗時返回SOCKET_ERROR;
*/
int recv(SOCKET s, char *buf, int len, int flags);