BSD socket编程学习
1.socket簡介
BSD是實現TCP/IP協議通信的軟件系統,socket是應用編程接口,為app提供使用TCP/IP協議通信的接口。
網絡層IP提供點到點服務(IP地址標識),傳輸層TCP和UDP提供端到端的服務(端口號標識)。
2.socket地址結構
2.1 兩種socket結構
socket則需要包含了所有這些信息,IP地址,端口號等,那么socket的包含所有這些信息的數據結構和使用方式又是什么樣的呢?
有兩種socket地址包含了這些信息,一種是linux內核kernel所采用的存儲結構sockaddr, 另外一種是具有互聯網風格的sockaddr_in,這兩種格式是兼容的
//sys/socket.h
/* * [XSI] Structure used by kernel to store most addresses. */ struct sockaddr { __uint8_t sa_len; /* total length */ sa_family_t sa_family; /* [XSI] address family */ char sa_data[14]; /* [XSI] addr value (actually larger) */ };
可以看到OS采用的這種sockaddr結構 存儲絕大部分的地址
//netinet/in.h
/* * Socket address, internet style. */ struct sockaddr_in { __uint8_t sin_len; sa_family_t sin_family; in_port_t sin_port; struct in_addr sin_addr; char sin_zero[8]; };
/*
* Internet address (a structure for historical reasons)
*/
struct in_addr {
in_addr_t s_addr;
};
sockaddr_in這種風格的數據結構便于進行(因特網)網絡通信,所以常常需要在這兩種格式間進行轉換。
2.2 兩種socket地址結構轉換
對于轉換函數htons,htonl,inet_addr,inet_aton,inet_ntoa等
2.2.1 本地->網絡
將主機字節順序轉化為網絡字節順序:htons,htonl
htons 將主機的無符號短整型數轉換成網絡字節順序,與之相反的是ntohs;
htonl 將主機的無符號長整型的網絡字節順序,與之相反的是ntohl;
IP地址,將字符串轉換為32bit的IP地址:inet_addr,inet_aton
inet_addr 將字符串轉換為32bit二進制網絡字節序的ipv4地址(in_addr) e.g."127.0.0.1"-> uint32_t, 點分形式“a.b.c.d”任何一項都不能超過255,否則返回INADDR_NONE;
inet_aton將一個字符串IP地址轉化為一個32bit的網絡序列ipv4地址, 與inet_addr的區別就是它認為“a.b.c.d”中任意一項=255都是有效地, 與之相反的是inet_ntoa;
2.2.2 網絡->本地
將網絡字節順序轉化為主機字節順序:ntohs,ntohl
IP地址,將32bit的網絡IP地址 轉換為 點分形式字符串:inet_aton
2.2.3大端序和小端序
為什么要進行這些麻煩的轉化呢?
主要原因是在進行網絡通信時候,使用的是網絡字節順序NBO(Network Byte Order),按從高位到低位的順序存儲、發送,即MSB(高位字節優先),這樣避免兼容問題;
但是在本地主機存儲的時候,卻使用的是主機字節順序HBO(Host Byte Order),這是跟具體的CPU設計相關的。
這就引出另外一個問題:大端序和小端序。
大端序 最高字節數存儲在內存地址最低位(起始位)(可以簡單理解成尾端最大(高)字節)
假如現在內存中地址位為0x10的位置處,存儲了一個4B數據0x07654321 ->
| 地址 | 內容 | 數的字節位 |
| 0x13 | 0x21 | |
| 0x12 | 0x43 | |
| 0x11 | 0x65 | |
| 0x10 | 0x07 | 最高位 |
小端序最低字節數存儲在內存地址最低位(起始位)(可以簡單理解成尾端最小(低)字節)
假如現在內存中地址位為0x10的位置處,存儲了一個4B數據0x07654321 ->
| 地址 | 內容 | 數的字節位 |
| 0x13 | 0x07 | |
| 0x12 | 0x65 | |
| 0x11 | 0x43 | |
| 0x10 | 0x21 | 最低位 |
判斷方法,最好只看起始位(地址低位)是最高字節數據(大端序)還是最低字節數據(小端序)。
3.編程模型
Server
| 步驟 | 內容 | data structure/API | 備注 |
| 1 |
初始化socket地址(internet風格 協議簇, IP地址, 端口號) |
struct sockaddr_in |
無 |
| 2 | 創建socket (tcp/udp, 字節流等) | socket() | 無 |
| 3 | 綁定socket和socket地址(本地系統風格) | bind() | 無 |
| 4 | 監聽socket(IP地址和端口) | listen() | 無 |
| 5* | 接收連接請求 | accept() | 響應客戶端連接請求connect() |
| 6* | 發送數據 | send() | 向連接的客戶端發送數據 |
| 7* | 接收數據 | recv() | 接收連接的客戶端發送數據 |
| 8 | 關閉socket | close() | 無 |
總結
以上是生活随笔為你收集整理的BSD socket编程学习的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python 函数递归_Python零基
- 下一篇: jsp的文件包含漏洞