日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

同一进程中同一端口如何区分不同的Socket

發(fā)布時(shí)間:2025/3/15 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 同一进程中同一端口如何区分不同的Socket 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

?為了區(qū)分不同應(yīng)用進(jìn)程間的網(wǎng)絡(luò)通信和連接,主要有3個(gè)參數(shù)通信的目的IP地址、使用的傳輸層協(xié)議(TCP 或 UDP)使用的端口號。

??? Socket的原意是“插座”。通過將這3個(gè)參數(shù)結(jié)合起來,與一個(gè)“插座”Socket綁定,應(yīng)用層就可以和傳輸層通過套接字接口,區(qū)分來自不同應(yīng)用程序進(jìn)程或網(wǎng)絡(luò)連接的通信,實(shí)現(xiàn)數(shù)據(jù)傳輸?shù)牟l(fā)服務(wù)。

??? accept()產(chǎn)生的Socket端口號是多少?

??? 要寫網(wǎng)絡(luò)程序就必須用Socket,這是程序員都知道的。而且,面試的時(shí)候,我們也會問對方會不會Socket編程?一般來說,很多人都會說,Socket編程基本就是listen, accept, 以及send, write等幾個(gè)基本的操作。是的,就跟常見的文件操作一樣,只要寫過就一定知道。

??? 對于網(wǎng)絡(luò)編程,我們也言必稱TCP/IP,似乎其他網(wǎng)絡(luò)協(xié)議已經(jīng)不存在了。對于TCP/IP,我們還知道TCP和UDP,前者可以保證數(shù)據(jù)的正確和可靠性,后者則允許數(shù)據(jù)丟失。最后,我們還知道,在建立連接前,必須知道對方的IP地址和端口號。除此,普通的程序員就不會知道太多了,很多時(shí)候這些知識已經(jīng)夠用了。最多,寫服務(wù)程序的時(shí)候,會使用多線程來處理并發(fā)訪問。

我們還知道如下幾個(gè)事實(shí):

1.?一個(gè)指定的端口號不能被多個(gè)應(yīng)用程序共用。比如,如果IIS占用了80端口,那么Apache就不能也用80端口了;

2.?很多防火墻只允許特定目標(biāo)端口的數(shù)據(jù)包通過。

3. 服務(wù)程序在listen某個(gè)端口并accept某個(gè)連接請求后,會生成一個(gè)新的socket來對請求進(jìn)行處理。

??? 于是,一個(gè)困惑了我很久的問題就產(chǎn)生了,如果一個(gè)socket創(chuàng)建后并與80端口綁定后,是否就意味著該socket占用了80端口呢?

??? 如果是這樣的,那么當(dāng)其accept一個(gè)請求后,生成的新的socket到底使用的是什么端口呢(我一直以為系統(tǒng)會默認(rèn)給其分配一個(gè)空閑的端口號)?

??? 如果是一個(gè)空閑的端口,那么一定不是80端口了,于是以后的TCP數(shù)據(jù)包的目標(biāo)端口就不是80了——防火墻一定會阻止其通過的!

??? 實(shí)際上,我們可以看到,防火墻并沒有阻止這樣的連接,而且這是最常見的連接請求和處理方式。我不理解的就是,為什么防火墻沒有阻止這樣的連接?它是如何判斷那條連接是因?yàn)閏onnect80端口而生成的?是不是TCP數(shù)據(jù)包里有什么特別的標(biāo)志?或者防火墻記住了什么東西?

??????后來,我又仔細(xì)研讀了TCP/IP的協(xié)議棧原理,對很多概念有了更深刻的認(rèn)識。比如,TCP和UDP同屬傳輸層,共同架設(shè)在IP層(網(wǎng)絡(luò)層)之上。而IP層主要負(fù)責(zé)的是在節(jié)點(diǎn)之間(End to End)的數(shù)據(jù)包傳送,這里的節(jié)點(diǎn)是一臺網(wǎng)絡(luò)設(shè)備,比如計(jì)算機(jī)。因?yàn)镮P層只負(fù)責(zé)把數(shù)據(jù)送到節(jié)點(diǎn)上,而不能區(qū)分上面的不同應(yīng)用所以TCP和UDP協(xié)議在其基礎(chǔ)上加入了端口的信息,端口于是標(biāo)識的是一個(gè)節(jié)點(diǎn)上的一個(gè)應(yīng)用。除了增加端口信息,UDP協(xié)議基本就沒有對IP層的數(shù)據(jù)進(jìn)行任何處理了。而TCP協(xié)議還加入了更復(fù)雜的傳輸控制,比如滑動的數(shù)據(jù)發(fā)送窗口(Slice Window),以及接收確認(rèn)和重發(fā)機(jī)制,以達(dá)到數(shù)據(jù)的可靠傳送。不管應(yīng)用層看到的是怎樣一個(gè)穩(wěn)定的TCP數(shù)據(jù)流,下面?zhèn)魉偷亩际且粋€(gè)個(gè)的IP數(shù)據(jù)包,需要由TCP協(xié)議來進(jìn)行數(shù)據(jù)重組

?????? 所以,我有理由懷疑,防火墻并沒有足夠的信息判斷TCP數(shù)據(jù)包的更多信息,除了IP地址和端口號。而且,我們也看到,所謂的端口,是為了區(qū)分不同的應(yīng)用的,以在不同的IP包來到的時(shí)候能夠正確轉(zhuǎn)發(fā)

??????TCP/IP只是一個(gè)協(xié)議棧,就像操作系統(tǒng)的運(yùn)行機(jī)制一樣,必須要具體實(shí)現(xiàn),同時(shí)還要提供對外的操作接口。就像操作系統(tǒng)會提供標(biāo)準(zhǔn)的編程接口,比如Win32編程接口一樣,TCP/IP也必須對外提供編程接口,這就是Socket編程接口——原來是這么回事啊!

??????在Socket編程接口里,設(shè)計(jì)者提出了一個(gè)很重要的概念,那就是socket。這個(gè)socket跟文件句柄很相似,實(shí)際上,在BSD系統(tǒng)里就是跟文件句柄一樣存放在一樣的進(jìn)程句柄這個(gè)socket其實(shí)是一個(gè)序號,表示其在句柄表中的位置這一點(diǎn),我們已經(jīng)見過很多了,比如文件句柄,窗口句柄等。這些句柄,其實(shí)是代表了系統(tǒng)中的某些特定的對象,用于在各種函數(shù)中作為參數(shù)傳入,以對特定對象進(jìn)行操作——這其實(shí)是C語言的問題,在C++語言里,這個(gè)句柄其實(shí)就是this指針,實(shí)際就是對象指針啦。

現(xiàn)在我們知道,socket跟TCP/IP并沒有必然的聯(lián)系。Socket編程接口在設(shè)計(jì)的時(shí)候,就希望也能適應(yīng)其他的網(wǎng)絡(luò)協(xié)議。所以,socket的出現(xiàn)只是可以更方便的使用TCP/IP協(xié)議棧而已,其對TCP/IP進(jìn)行了抽象,形成了幾個(gè)最基本的函數(shù)接口。比如create, listen, accept, connect, read和write等。

現(xiàn)在我們明白,如果一個(gè)程序創(chuàng)建了一個(gè)socket,并讓其監(jiān)聽80端口,其實(shí)是向TCP/IP協(xié)議棧聲明了其對80端口的占有。以后,所有目標(biāo)是80端口的TCP數(shù)據(jù)包都會轉(zhuǎn)發(fā)給該程序(這里的程序,因?yàn)槭褂玫氖荢ocket編程接口,所以首先由Socekt層來處理)。所謂的accept函數(shù),其實(shí)抽象的是TCP的連接建立過程。accept函數(shù)返回的新socket其實(shí)指代的是本次創(chuàng)建的連接,而一個(gè)連接是包括兩部分信息的,一個(gè)是源IP和源端口,另一個(gè)宿IP和宿端口這樣的話,這些socket宿端口就可以都是80!而同時(shí),防火墻的對IP包的處理規(guī)則也是清晰明了,不存在前面設(shè)想的種種復(fù)雜的情形。

??????明白socket只是對TCP/IP協(xié)議棧操作的抽象,而不是簡單的映射關(guān)系,這很重要!


昨天和朋友聊了下網(wǎng)絡(luò)編程,關(guān)于Socket,這里寫一下我個(gè)人的一些理解:)

程序里可以創(chuàng)建Socket,分為普通Socket和原始Socket兩種類型。

一:普通Socket是對TCP/IP協(xié)議棧中傳輸層的操作的編程接口(一種API)。

有面向連接的流式套接字(SOCK_STREAM),屬于針對TCP方式的應(yīng)用;

有無連接數(shù)據(jù)包式套接字(SOCK_DGRAM),屬于針對UDP方式的應(yīng)用。

??????對于普通Socket,我曾經(jīng)有個(gè)模糊的問題,在多線程情況下,服務(wù)器端監(jiān)聽(listen)某個(gè)端口(假設(shè)8080)后,每accept一個(gè)客戶端的連接就會產(chǎn)生一個(gè)新的Socket。那么這些新產(chǎn)生的Socket的端口是什么?程序里肯定沒有指定,那就應(yīng)該有兩種可能,1:產(chǎn)生隨機(jī)端口。2:還是8080端口。第一種假設(shè)想了就覺得不可能,防火墻非常有可能會阻止這些隨機(jī)端口的包。那么就是第二種假設(shè)了,服務(wù)端端口還是8080。但這推翻了我原有的認(rèn)識,就是“一個(gè)端口被程序占有,其他程序就不能用該端口了”。我覺得其實(shí)最有可能的是范圍不同:就是在程序與程序間不能用同一端口,但是在程序內(nèi)部不同的Socket還是可以用同一端口的。所以,為了能夠使“客戶端發(fā)給服務(wù)端的同一端口(8080)不同線程(即不同的Socket連接)的包能夠被區(qū)分開并進(jìn)行組合”,必須得有一個(gè)區(qū)分包是來自不同連接的顯著特征,那就是傳輸層包頭里的源端口了,即一個(gè)Socket連接里客戶端那方的端口??偨Y(jié)一下,對于這種情況,就是傳輸層包頭里源端口(客戶端)會隨著產(chǎn)生的Socket不同,而宿端口相同(服務(wù)器端)。

二:原始Socket,建立在網(wǎng)絡(luò)層上,所以我們可以在傳輸層上構(gòu)建自己的協(xié)議。

如果是自己做個(gè)Sniffer(網(wǎng)絡(luò)嗅探器),那么監(jiān)聽到的包是來自同一網(wǎng)段的普通Socket包(TCP方式或UDP方式),所以在程序里我們要自己寫數(shù)據(jù)結(jié)構(gòu)(IP頭和TCP或UDP頭),并綁定數(shù)據(jù)。

如果是客戶端和服務(wù)端都是由自己用原始Socket寫的,那么可以自己控制協(xié)議,像一些網(wǎng)絡(luò)應(yīng)用(MSN, skype等),可以在網(wǎng)絡(luò)層往上重寫協(xié)議。

總結(jié)

以上是生活随笔為你收集整理的同一进程中同一端口如何区分不同的Socket的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。