TCP/UDP對比
- TCP面向連接(如打電話要先撥號建立連接);UDP是無連接的,即發送數據之前不需要建立連接
- TCP提供可靠的服務。也就是說,通過TCP連接傳送的數據,無差錯,不丟失,不重複,且按序到達;UDP盡最大努力交付,即不保證可靠交付
- TCP面向字節流,實際上是TCP把數據看成一連串無結構的字節流;UDP是面向報文的
UDP沒有擁塞控制,因此網絡出現擁塞不會使源主機的發送速率降低(對實時應用很有用,如IP電話,實時視頻會議等) - 每一條TCP連接只能是點到點的;UDP支持一對一,一對多,多對一和多對多的交互通信
- TCP首部開銷20字節;UDP的首部開銷小,只有8個字節
- TCP的邏輯通信信道是全雙工的可靠信道,UDP則是不可靠信道
端口號作用
1.一臺擁有IP地址的主機可以提供許多服務,比如Web服務、FTP服務、SMTP服務等
2.這些服務完全可以通過1個IP地址來實現。那麼,主機是怎樣區分不同的網絡服務呢?顯然不能只靠IP地址,因爲IP 地址與網絡服務的關係是一對多的關係。
3.實際上是通過“IP地址+端口號”來區 分不同的服務的。
端口提供了一種訪問通道,
服務器一般都是通過知名端口號來識別的。例如,對於每個TCP/IP實現來說,FTP服務器的TCP端口號都是21,每個Telnet服務器的TCP端口號都是23,每個TFTP(簡單文件傳送協議)服務器的UDP端口號都是69
注:自己在使用的時候最好選擇端口號5000以上的端口,因爲,5000以內是系統使用的
字節序
字節序,即字節在電腦中存放時的序列與輸入(輸出)時的序列是先到的在前還是後到的在前。
概述
字節序是指多字節數據在計算機內存中存儲或者網絡傳輸時各字節的存儲順序。
常見序
1. Little endian:將低序字節存儲在起始地址
2. Big endian:將高序字節存儲在起始地址
LE little-endian
最符合人的思維的字節序,地址低位存儲值的低位,地址高位存儲值的高位
怎麼講是最符合人的思維的字節序,是因爲從人的第一觀感來說低位值小,就應該放在內存地址小的地方,也即內存地址低位
反之,高位值就應該放在內存地址大的地方,也即內存地址高位
BE big-endian
最直觀的字節序,地址低位存儲值的高位,地址高位存儲值的低位
爲什麼說直觀,不要考慮對應關係,只需要把內存地址從左到右按照由低到高的順序寫出把值按照通常的高位到低位的順序寫出
兩者對照,一個字節一個字節的填充進去
例子:
在內存中雙字0x01020304(DWORD)的存儲方式
內存地址
4000&4001&4002&4003
LE 04 03 02 01
BE 01 02 03 04
例子:如果我們將0x1234abcd寫入到以0x0000開始的內存中,則結果爲
big-endianlittle-endian
0x0000 0x12 0xcd
0x0001 0x34 0xab
0x0002 0xab 0x34
0x0003 0xcd 0x12
注:
x86系列CPU都是little-endian的字節序.
網絡字節序等於大端字節序
字節序轉換api
#include <netinet/in.h>
uint16_t htons(uint16_t host16bitvalue); //返回網絡字節序的值
uint32_t htonl(uint32_t host32bitvalue); //返回網絡字節序的值
uint16_t ntohs(uint16_t net16bitvalue); //返回主機字節序的值
uint32_t ntohl(uint32_t net32bitvalue); //返回主機字節序的值
注:
h代表host,n代表net,s代表short(兩個字節),l代表long(4個字節),通過上面的4個函數可以實現主機字節序和網絡字節序之間的轉換。有時可以用INADDR_ANY,INADDR_ANY指定地址讓操作系統自己獲取
socket服務器和客戶端的開發步驟
- 創建套接字(socket)
- 爲套接字添加信息(IP地址和端口號)(bind)
- 監聽網絡連接(listen)
- 監聽到有客戶端接入,接受一個連接(accept)
- 數據交互(read,write)
- 關閉套接字,斷開連接
連接協議(socket)
1.創建套接字socket
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int socket(int domain,int type,int protocol);
注:國內一般使用IPV4
添加地址信息(bind)
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
地址轉換API
1.int inet_aton(const char* straddr,struct in_addr *addrp);
把字符串形式的“192.168.1.123”轉爲網絡能識別的格式
2.char* inet_ntoa(struct in_addr inaddr);
把網絡格式的ip地址轉爲字符串形式
監聽(listen)
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int listen(int sockfd, int backlog);
連接(accept)
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
數據收發
第一種:
第二種: