TCP/UDP概念介紹
一、TCP/UDP對比
- TCP面向連接(如打電話要先撥號建立連接);UDP是無連接的,即發(fā)送數(shù)據(jù)之前不需 要建立連接
- TCP提供可靠的服務(wù)。也就是說,通過TCP連接傳送的數(shù)據(jù),無差錯,不丟失,不重復(fù),且按序到達;UDP盡最大努力交付,即不保證可靠交付
- TCP面向字節(jié)流,實際上是TCP把數(shù)據(jù)看成一連串無結(jié)構(gòu)的字節(jié)流;UDP是面向報文的。UDP沒有擁塞控制,因此網(wǎng)絡(luò)出現(xiàn)擁塞不會使源主機的發(fā)送速率降低(對實時應(yīng)用很有用,如IP電話,實時視頻會議等)
- 每一條TCP連接只能是點到點的;UDP支持一對一,一對多,多對一和多對多的交互通信
- TCP首部開銷20字節(jié);UDP的首部開銷小,只有8個字節(jié)
- TCP的邏輯通信信道是全雙工的可靠信道,UDP則是不可靠信道
二、端口號的作用
一臺擁有IP地址的主機可以提供許多服務(wù),比如Web服務(wù)、FTP服務(wù)、SMTP服務(wù)等。這些服務(wù)完全可以通過1個IP地址來實現(xiàn)。那么,主機是怎樣區(qū)分不同的網(wǎng)絡(luò)服務(wù)呢?顯然不能只靠IP地址,因為IP 地址與網(wǎng)絡(luò)服務(wù)的關(guān)系是一對多的關(guān)系。
實際上是通過IP地址+端口號來區(qū) 分不同的服務(wù)的。
端口提供了一種訪問通道,服務(wù)器一般都是通過知名端口號來識別的。
例如,對于每個TCP/IP實現(xiàn)來說,F(xiàn)TP服務(wù)器的TCP端口號都是21,每個Telnet服務(wù)器的TCP端口號都是23,每個TFTP(簡單文件傳送協(xié)議)服務(wù)器的UDP端口號都是69
三、字節(jié)序
1、概念
字節(jié)序,就是多字節(jié)類型的數(shù)據(jù)在計算機內(nèi)存中存儲或者網(wǎng)絡(luò)傳輸時各字節(jié)的存放順序。是在跨平臺和網(wǎng)絡(luò)編程中,時常要考慮的問題
2、分類
字節(jié)序經(jīng)常被分為兩類:
1. Big-Endian(大端):高位字節(jié)排放在內(nèi)存的低地址端,低位字節(jié)排放在內(nèi)存的高地址端。
2.Little-Endian(小端):低位字節(jié)排放在內(nèi)存的低地址端,高位字節(jié)排放在內(nèi)存的高地址端。
3.網(wǎng)絡(luò)字節(jié)序=大端字節(jié)序
樣例介紹:
在內(nèi)存中雙字0x01020304(DWORD)的存儲方式
內(nèi)存地址
4000&4001&4002&4003
LE 04 03 02 01
BE 01 02 03 04
3、C程序在內(nèi)存空間的映射
C程序映射中內(nèi)存的空間布局大致如下:
最高內(nèi)存地址 0xFFFFFFFF
棧區(qū)(從高內(nèi)存地址,往 低內(nèi)存地址發(fā)展。即棧底在高地址,棧頂在低地址)
堆區(qū)(從低內(nèi)存地址 ,往 高內(nèi)存地址發(fā)展)
全局區(qū)(常量和全局變量)
代碼區(qū)
最低內(nèi)存地址 0x00000000文章來源:http://www.zghlxwxcb.cn/news/detail-402565.html
socket服務(wù)器與客戶端開發(fā)流程
一、流程介紹
詳細說明:文章來源地址http://www.zghlxwxcb.cn/news/detail-402565.html
- socket() 創(chuàng)建套接字
- bind() 為套接字添加信息(IP地址+端口號)
- listen() 監(jiān)聽網(wǎng)絡(luò)連接(客戶端接入)
- accept() 監(jiān)聽到有客戶端接入,接收一個連接
- read/write 數(shù)據(jù)交互
- close() 關(guān)閉套接字,斷開連接
二、socket服務(wù)器搭建API介紹
1、scoket() 創(chuàng)建套接字
//**創(chuàng)建套接字**
int socket(int domain, int type, int protocol);
- domain:
指明所使用的協(xié)議族,通常為AF_INET,表示互聯(lián)網(wǎng)協(xié)議族(TCP/IP協(xié)議族):
- AF_INET IPv4因特網(wǎng)域
- AF_INET6 IPv6因特網(wǎng)域
- AF_UNIX Unix域
- AF_ROUTE 路由套接字
- AF_KEY 秘鑰套接字
- AF_UNSPEC 未指定
- type:
指定socket的類型:
- SOCK_STREAM:
流式套接字提供可靠的、面向連接的通信流;它使用TCP協(xié)議,從而保證了數(shù)據(jù)傳輸?shù)恼_性和順序性
- SOCK_DGRAM:
數(shù)據(jù)報套接字定義了一種無連接的服務(wù),數(shù)據(jù)通過相互獨立的報文進行傳輸,是無序的,并且不保證是可靠、無差錯的。它使用數(shù)據(jù)報協(xié)議UDP。
- SOCK_RAW:
允許程序使用低層協(xié)議,原始套接字允許對低層協(xié)議如IP或者ICMP進行直接訪問,功能強大但使用較為不便,主要用于一些協(xié)議棧的開發(fā)。
- protocol:
通常賦值“0”
- 0選擇type類型對應(yīng)的默認協(xié)議
- IPPROTO_TCP TCP傳輸協(xié)議
- IPPROTO_UDP UDP傳輸協(xié)議
- IPPROTO_SCTP SCTP傳輸協(xié)議
- IPPROTO_SCTP TIPC傳輸協(xié)議
2、bind() 將套接字與地址關(guān)聯(lián)
//關(guān)聯(lián)地址和套接字
#include <sys/types.h>
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
功能:
用于綁定IP地址和端口號到socketfd
參數(shù):
- sockfd 是一個socket描述符
- addr 是一個指向包含有本機IP地址及端口號等信息的sockaddr類型的指針,指向要綁定給
sockfd的協(xié)議地址結(jié)構(gòu)。這個地址結(jié)構(gòu)根據(jù)地址創(chuàng)建socket時的地址協(xié)議族的不同而不同
- addrlen 套接字的大小
IPv4對應(yīng)的是:
struct sockaddr {
unsigned short sa_family; //協(xié)議族
char sa_data[14]; //IP+端口
}
同等替換:
struct sockaddr_in {
sa_family_t sin_family; /*協(xié)議族*/
in_port_t sin_port; /*端口號*/
struct in_addr sin_addr; /*IP地址結(jié)構(gòu)體*/
unsigned char sin_zero[8]; /*填充 沒有實際意義,只是為跟sockaddr結(jié)構(gòu)在內(nèi)存中對齊,這樣兩者才能相互轉(zhuǎn)換*/
}
3、地址轉(zhuǎn)換API
1. 把字符串形式的“192.168.1.123”轉(zhuǎn)為網(wǎng)絡(luò)能識別的格式
int inet_aton(const char* straddr,struct in_addr *addrp);
功能:
將一個字符串表示的點分十進制IP地址IP轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)序存儲在addr中,并且返回該網(wǎng)絡(luò)字節(jié)序表示的無符號整數(shù)。
參數(shù):
const char *straddr: 我們輸入的點分十進制的IP地址
struct in_addr* addr: 將IP轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)序(大端存儲)后并保存在addr中
返回值:
成功;返回點分十進制的IP地址對應(yīng)的網(wǎng)絡(luò)字節(jié)序表示的無符號整數(shù)
失??;返回0
2. 把網(wǎng)絡(luò)格式的ip地址轉(zhuǎn)為字符串形式
char* inet_ntoa(struct in_addr inaddr);
功能:
將一個網(wǎng)絡(luò)字節(jié)序的IP地址(也就是結(jié)構(gòu)體in_addr類型變量)轉(zhuǎn)化為點分十進制的IP地址(字符串)
參數(shù):
struct in_addr{
in_addr_t s_addr;
};
in_addr是一個按網(wǎng)絡(luò)順序存儲的IP地址
返回值:
該函數(shù)的返回值是一個字符串,這個字符串是點分十進制的IP地址
4、listen() 監(jiān)聽
//監(jiān)聽設(shè)置函數(shù)
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int listen(int sockfd, int backlog);
功能:
- 設(shè)置能處理的最大連接數(shù),listen()并未開始接收連線,只是設(shè)置socket的listen模式,listen函數(shù)只用于服務(wù)器端,服務(wù)器進程不知道要與誰連接,
因此,它不會主動地要求與某個進程連接,只是一直監(jiān)聽是否有其他客戶進程與之連接,然后響應(yīng)該連接請求,并對它作出處理,一個服務(wù)進程可以同時處理多個客戶進程的連接。
主要就兩個功能:將一個未連接的套接字轉(zhuǎn)換為一個被動套接字(監(jiān)聽),規(guī)定內(nèi)核為相應(yīng)套接字排隊的最大連接數(shù)。
- 內(nèi)核為任何一個給定監(jiān)聽套接字維護兩個隊列:
- 未完成連接隊列,每個這樣的SYN報文端對應(yīng)其中一項;已由某個客戶端發(fā)出并到達服務(wù)器,而服務(wù)器正在等待完成相應(yīng)的TCP三次握手過程。這些套接字處于SYN_REVD狀態(tài)。
- 已完成連接隊列,每個已完成TCP三次握手過程的客戶端對應(yīng)其中一項。這些套接字處于ESTABLISHED狀態(tài)
參數(shù):
- sockfd:sockfd是socket系統(tǒng)調(diào)用返回的服務(wù)端socket描述符
- backlog:backlog指定在請求隊列中允許的最大請求數(shù)
5、accept 連接
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
功能:
accept函數(shù)由TCP服務(wù)器調(diào)用,用于從已完成連接隊列隊頭返回下一個已完成連接。如果已完成連接隊列為空,那么進程進入睡眠。
參數(shù):
sockfd: 是socket系統(tǒng)調(diào)用返回的服務(wù)器端socket描述符
addr: 用來返回已連接的對端(客戶端)的協(xié)議地址
addrled:客戶端地址長度
返回值:
該函數(shù)的返回值是一個新的套接字描述符,返回值是表示已經(jīng)連接的套接字描述符,而第一個參數(shù)是服務(wù)器監(jiān)聽套接字描述符。
一個服務(wù)器通常僅僅創(chuàng)建一個監(jiān)聽套接字,它在該服務(wù)器的生命周期內(nèi)一直存在。
內(nèi)核為每個由服務(wù)器進程接收的客戶連接創(chuàng)建一個已連接套接字(表示TCP三次握手已經(jīng)完成),當服務(wù)器完成對某個給定客戶的服務(wù)時,相應(yīng)的已連接套接字就會被關(guān)閉。
6、數(shù)據(jù)收發(fā)
//字節(jié)流讀取函數(shù)
在套接字通信中進行字節(jié)讀取函數(shù):read(),write().與I/O中的讀取函數(shù)略有區(qū)別,因為他們輸入或輸出的字節(jié)數(shù)可能比請求的少。
ssize_t write(int fd, const void*buf,size_t nbytes);
ssize_t read(int fd,void *buf,size_t nbyte);
/*說明
*函數(shù)均返回讀或?qū)懙淖止?jié)個數(shù),出錯則返回-1
*/
第一個將buf中的nbytes個字節(jié)寫入到文件描述符fd中,成功時返回寫的字節(jié)數(shù)。
第二個為從fd中讀取nbyte個字節(jié)到buf中,返回實際所讀的字節(jié)數(shù)。詳細應(yīng)用說明參考使用read、write讀寫socket(套節(jié)字)。
網(wǎng)絡(luò)I/O還有一些函數(shù),例如:recv()/send(),readv()/writev(),recvmsg()/sendmsg(),recvfrom()/sendto()等。
數(shù)據(jù)收發(fā)常用第二套API
1.在TCP套接字上發(fā)送數(shù)據(jù)函數(shù):有連接
ssize_t send(int s,const void *msg,size_t len,int flags);
//包含3要素:套接字s,待發(fā)數(shù)據(jù)msg,數(shù)據(jù)長度len
//函數(shù)只能對處于連接狀態(tài)的套接字使用,參數(shù)s為已建立好連接的套接字描述符,即accept函數(shù)的返回值
//參數(shù)msg指向存放待發(fā)送數(shù)據(jù)的緩沖區(qū)
//參數(shù)len為待發(fā)送數(shù)據(jù)的長度,參數(shù)flags為控制選項,一般設(shè)置為0
2.在TCP套接字上接收數(shù)據(jù)函數(shù):有連接
ssize_t recv(int s,void *buf,size_t len,int flags);
//包含3要素:套接字s,待發(fā)數(shù)據(jù)msg,數(shù)據(jù)長度len
//函數(shù)recv從參數(shù)s所指定的套接描述符(必須是面向連接的套接字)上接收
//數(shù)據(jù)并保存到參數(shù)buf所指定的緩沖區(qū)
//參數(shù)len則為緩沖區(qū)長度,參數(shù)flags為控制選項,一般設(shè)置為0
7、connect()
//客戶機連接主機
#include <sys/types.h>
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
功能:
該函數(shù)用于綁定之后的client端(客戶端),與服務(wù)器建立連接
參數(shù):
sockfd:是目的服務(wù)器的socket描述符
addr:是服務(wù)器端的IP地址和端口號的地址結(jié)構(gòu)指針
addrlen:地址長度常設(shè)置為sizeof(struct sockaddr)
返回值:
成功返回0,遇到錯誤時返回-1,并且errno中包含相應(yīng)的錯誤碼
到了這里,關(guān)于基于TCP/UDP的socket服務(wù)器搭建流程的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!