網(wǎng)絡(luò)七層協(xié)議:
其中茸俭,傳輸層:
同一臺機器的同一個端口只可以被一個進程使用,一般用于tcp安皱,或者udp调鬓。那一個進程使用同一個端口同時監(jiān)聽tcp、udp請求酌伊,是否可以呢腾窝?
答案:可以。
端口可以形象地比喻成操作系統(tǒng)上的編號唯一的文件居砖,應(yīng)用程序和網(wǎng)絡(luò)協(xié)議可以對其進行i/o操作虹脯。
但是既然唯一又為何tcp udp可以用相同的端口號呢?這樣的話悯蝉,程序在連接到端口時归形,怎么知道此時從該端口進來的數(shù)據(jù)是tcp的還是udp的呢?
是不是可以這樣理解鼻由?端口的唯一性的標(biāo)識不是端口號,而是端口號和協(xié)議名稱的組合厚棵,應(yīng)用程序和協(xié)議尋址時就是靠的這個組合蕉世?
使用netstat -an自己看看就知道了,IP數(shù)據(jù)包首部有個叫做協(xié)議的字段婆硬,指出了上層協(xié)議是TCP還是UDP還是其他P狠轻。
協(xié)議字段(報頭檢驗和前面那個),其值為6彬犯,則為TCP向楼;
其值為17,則為UDP谐区。
[root@web ~]# netstat -an
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:46997 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
tcp 0 64 10.0.0.7:22 10.0.0.253:61752 ESTABLISHED
tcp 0 0 :::3306 :::* LISTEN
tcp 0 0 :::111 :::* LISTEN
tcp 0 0 :::22 :::* LISTEN
tcp 0 0 :::40566 :::* LISTEN
udp 0 0 127.0.0.1:967 0.0.0.0:*
udp 0 0 0.0.0.0:34398 0.0.0.0:*
udp 0 0 0.0.0.0:111 0.0.0.0:*
udp 0 0 0.0.0.0:944 0.0.0.0:*
udp 0 0 :::111 :::*
udp 0 0 :::944 :::*
udp 0 0 :::19764 :::*
操作系統(tǒng)有能力根據(jù)接受的報文的IP字段里面的協(xié)議部分判斷這個報文是什么報文湖蜕。
就是說,系統(tǒng)讀數(shù)據(jù)的時候還沒有讀到上層報文(TCP/UDP)的時候已經(jīng)知道上層是什么報文了宋列,直接交給相關(guān)的內(nèi)核進程或協(xié)議棧處理就可以了昭抒。而在同一個協(xié)議內(nèi)部端口號唯一。
TCP和UDP為何可以共用同一端口
一:何為端口盗迟?
從網(wǎng)絡(luò)層的角度來看,它是不知道端口這個概念的熙含,tcp\udp都是包裹在ip協(xié)議內(nèi)的罚缕,ip協(xié)議只需要知道ip對應(yīng)的硬件地址就可以把遠端的網(wǎng)絡(luò)包發(fā)送到目的主機上。
端口這個概念是由操作系統(tǒng)劃分的怎静。因為內(nèi)核不可能把所有網(wǎng)絡(luò)數(shù)據(jù)都發(fā)送給所有的進程邮弹,所以為了區(qū)分哪些數(shù)據(jù)該劃分給哪些進程,便在傳輸層的協(xié)議中定義了端口消约。而tcp和udp協(xié)議中的端口號占位都是16位肠鲫,所以操作系統(tǒng)能綁定的端口也就只有65535個。這也解釋了為什么linux里設(shè)置單個進程所能打開的最大文件描述符數(shù)量最好設(shè)置為65535或粮。關(guān)于文件描述符和端口又有什么關(guān)系导饲,下面會進行說明。
二:如何綁定端口氯材?
這里需要用c語言的系統(tǒng)函數(shù)去解釋:
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
這個函數(shù)用來創(chuàng)建socket套接字描述符也就是文件描述符渣锦。
其中type參數(shù):
SOCK_STREAM —— TCP協(xié)議
SOCK_DGRAM —— UDP協(xié)議
SOCK_SEQPACKET —— ipx/spx協(xié)議
而返回的int值就是一個非負的文件描述符fd。linux內(nèi)核中維護了一份文件描述符表氢哮,如下圖袋毙,來存儲文件描述符fd。
#include <sys/socket.h>
int bind(int socket, const struct sockaddr *address,socklen_t address_len);
這個函數(shù)用來綁定端口冗尤,socket參數(shù)就是fd听盖,而sockaddr則是一個套接字地址結(jié)構(gòu)。
sockaddr結(jié)構(gòu)如下:
sa_family_t sin_family /*描述是文件還是套接字*/
in_port_t sin_port /*端口*/
struct in_addr sin_addr /*ip*/
unsigned char sin_zero[8] /*sizeof(struct sockaddr)*/
可以看到linux是以協(xié)議裂七、ip皆看、端口來綁定端口的,所以不同協(xié)議相同的ip和端口也是可以綁定成功的背零。