文章內容節選《linux/UNIX 系統網絡編程》
Internet domain socket地址有兩種:IPv4 IPv6
IPv4被存儲在結構體中, 該結構體在 netinet/in.h 中進行定義
cd usr/include/netinet/in.h
struct in_addr
{in_addr_t s_addr; //32位IPv4地址
}struct sockaddr_in
{sa_family_t sin_family; //地址族in_port_t sin_port; //16位TCP/UDP端口號struct in_addr sin_addr; //32位IP地址unsigned char __pad[X]; //不用這個
};
sin_family
每種協議族適用的地址族均不同.如IPv4使用4字節地址族,IPv6使用16字節地址族.sa_family是協議簇通常大多用的是都是AF_INET,表示tcpip協議。
用法
struct sockaddr_in server_address;
server_address.sin_family=AF_INET;
AF_INET(又稱 PF_INET)是 IPv4 網絡協議的套接字類型
AF_INET6 則是 IPv6 的
sin_port
以網絡字節序保存16位端口號
為了使網絡程序具有可移植性,使同樣的C代碼在大端和小段計算機上編譯后都能正常運行,可以調用以下庫函數做網絡字節序和主機字節序的轉換。
#include <arpa/inet.h>
uint16_t htons(uint16_t hostshort);
h表示Host,n表示Network,l表示32為長整數,s表示16位短整數
如果主機是小端字節序,這些函數將參數做相應的大小端轉換后返回
如果主機是大端字節序,這些函數不做轉換,將參數直接返回
用法:
int main(int argc, char* argv[])
{
//輸入./a.out 192.168.42.1 9000
addr.sin_port = htons(atoi(argv[2]));
}
sin_addr
用法
server_address.sin_addr.s_addr=inet_addr("127.0.0.1");
以網絡字節序保存32位IP地址信息.
socket套接字:
socket起源于Unix,而Unix/Linux基本哲學之一就是“一切皆文件”,都可以用“打開open –> 讀寫write/read –> 關閉close”模式來操作。Socket就是該模式的一個實現,
socket即是一種特殊的文件,一些socket函數就是對其進行的操作(讀/寫IO、打開、關閉).
說白了Socket是應用層與TCP/IP協議族通信的中間軟件抽象層,它是一組接口。
套接字描述符
其實就是一個整數,我們最熟悉的句柄是0、1、2三個,0是標準輸入,1是標準輸出,2是標準錯誤輸出。0、1、2是整數表示的,對應的FILE *結構的表示就是stdin、stdout、stderr
文件描述符 | 對象 | FILE * | |
---|---|---|---|
0 | 標準輸入 | Standard Input | stdin |
1 | 標準輸出 | Standard Output | stdout |
2 | 標準錯誤 | Standard Error | stderr |
基于TCP/IP的服務器端/客戶端函數調用關系
TCP客戶端的默認函數調用順序
- socket()創建套接字
- connect()請求連接
- read()/write()交換數據
- close()斷開連接
TCP服務器端的默認函數調用順序
- socket()創建套接字
- bind()分配套接字地址
- listen()等待連接請求狀態
- accept()允許連接
- read()/write()數據交換
- close()斷開連接
函數
創建socket套接字(TCP/UDP,客戶端+服務器)
int socket(int domain,int type,int protocol);
綁定端口號(TCP/UDP,服務器)
int bind(int socket,const struct sockaddr *address,socklen_t address_len);
開始監聽socket(TCP,服務器)
int listen(int socket,int backlog);
接收請求(TCP,服務器)
int accept(int socket,struct sockaddr *address,socklen_t *address_len);
建立連接(TCP,客戶端)
int connect(int sockfd,const struct sockaddr *addr,socklen_t addrlen);