欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
TCP源端口選擇算法與列維模型
 發(fā)起一個(gè)TCP連接,4元組是必須的,即源IP,源端口,目標IP,目標端口。目標IP和端口都是確定的,源IP根據路由選擇或者bind也可以確定,基本上最終的源IP都是本機的IP地址,然而通過(guò)IP_TRANSPARENT參數可以bind一個(gè)不屬于本機的IP地址。唯一麻煩的就是源端口的確定。
       在繼續深入源端口選擇算法之前,必須要認識到一個(gè)大的前提,也算是源端口選擇算法的一個(gè)大的目標,那就是“必須保證TCP四元組的唯一性”!有了這個(gè)前提以及終極目標,TCP源端口的選擇算法就非常容易理解了。在以下的情況下需要算法來(lái)選擇一個(gè)源端口:
1.調用bind,但是bind的端口是0的時(shí)候;
2.沒(méi)有調用bind,直接調用connect的時(shí)候。

這兩種情況使不同的,因為在第一種情況下,4元組中的目標IP和目標端口是不確定的,而在第二種情況下,除了源端口,其它的都是知道的。所以?xún)煞N情況的端口分配算法是不同的。

1.bind情形的列維搜索算法

 對于bind的情形,由于缺失信息,需要采用非常嚴格的方式選擇源端口,即要做到:只要有可能四元組沖突,就不能分配。比如已經(jīng)有一個(gè)連接的四元組為:Tuple1(IPsrc,PORTsrc,IPdst,PORTdst),現在為一個(gè)新建立的套接字bind一個(gè)源端口,其不bind任何確定的IP地址,那么它就不能使用PORTsrc這個(gè)端口作為源端口,因為它可能和Tuple1沖突,雖然僅僅是可能而已!如下是算法的實(shí)現:
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <pthread.h>  
  4.   
  5. #define LOW     10000  
  6. #define HIGH    65535  
  7.   
  8. //端口分配函數  
  9. //base:一個(gè)(源IP,目標IP,目標端口)三元組的hash值  
  10. int get_local_port(int base )  
  11. {  
  12.         unsigned int i,j,port, remaining;  
  13. again:  
  14.         remaining = (HIGH - LOW) + 1;  
  15.         //采用隨機的方式更容易找到空閑端口  
  16.         port = LOW + random()%remaining;  
  17.         for (i = 1; i <= remaining; i++) {  
  18.                 int port_ok = 0;  
  19.                 //判斷該端口是否可用,由于四元組唯一性現在由于信息不全無(wú)法判斷,先檢查最容易匹配的:  
  20.                 //端口沒(méi)有處在TW狀態(tài),非LISTEN狀態(tài),可用  
  21.                 //此處要保證的是,聚集者要越往外越少。  
  22.                 port_ok = 1;  
  23.                 if (port_ok) {  
  24.                         goto check_inner;  
  25.                 }  
  26.                 //如果不合適就以port為基準,遞增  
  27.                 port ++;  
  28.         }  
  29. check_inner:  
  30.         {  
  31.                 //更深層次,但更耗時(shí)的判斷  
  32.                 int port_inner_ok;  
  33.                 port_inner_ok = 1;  
  34.                 if (!port_inner_ok) {  
  35.                         goto again;  
  36.                 }  
  37.         }  
  38.         return port;  
  39. }  
  40.   
  41. //分配端口函數  
  42. void func()  
  43. {  
  44.         while(1) {  
  45.                 int port = get_local_port(0);  
  46.                 printf(" %d \n", port);  
  47.                 sleep(1);  
  48.         }  
  49. }  
  50.   
  51. //main函數  
  52. int main(int argc, char **argv)  
  53. {  
  54.         func();  
  55.         return 0;  
  56. }  

可以看到,算法從一個(gè)隨機計算出的值為基準端口,然后通過(guò)一系列的判斷來(lái)得到該端口是否可用的信息,一共是兩層的判斷,如果外層簡(jiǎn)單判斷發(fā)現不可用,則遞增端口數值重新判斷,如果內層復雜判斷該端口不可用,則重新計算隨機基準端口重新開(kāi)始。使用這個(gè)算法可以很快定位到一個(gè)可用的端口。通過(guò)算法可以看得出,它符合列維模型,即在更近的局部細致掃描,然后飛躍到一個(gè)更遠的地方繼續列維查找。
       實(shí)際生活中,這種搜索是很高效的,深夜找賓館,到一個(gè)陌生的城市找工作,警察搜山...信天翁覓食...都是列維搜索!

2.connect情形的精確判定模式

connect的時(shí)候,四元組中的三元組已經(jīng)確定,因此可以精確匹配了,和bind時(shí)的端口選擇相反,此時(shí)只要有一個(gè)元組不同即可成功,記住我們的目標,即保證TCP四元組的唯一性!
       確定性的查找不需要列維搜索,而是大家都可以根據順序遞增加簡(jiǎn)單沖突判定的方式進(jìn)行端口選擇,最合常理的方式就是,每一個(gè)三元組(源IP,目標IP,目標端口)都可以有一個(gè)65534個(gè)端口可供選擇,每次遞增即可。但是這樣的話(huà)需要為每一個(gè)端口維護一個(gè)計數器,Linux使用了更加巧妙的方法,可以采用為每一個(gè)三元組用哈希計算一個(gè)確定的基準端口,全局維護一個(gè)遞增的計數器,根據這個(gè)計數器與基準端口之和和端口空間大小做模運算,這樣的一個(gè)取模操作可以確定一個(gè)offset,加上最小端口確定一個(gè)候選端口,這樣就保證了候選端口和三元組的線(xiàn)性關(guān)系,也就是說(shuō),每一個(gè)三元組獨立選擇端口。
       這么做的好處在于,對每一個(gè)三元組而言,都是從基準端口開(kāi)始順序分配的,相同三元組的端口都集中在一起,因為我們正是要和相同三元組的那些已經(jīng)確定的端口來(lái)比較,以判斷有沒(méi)有沖突,通過(guò)這種方式,將相同三元組的已經(jīng)分配的端口集中在了一起,省去了維護鏈表的麻煩,只需要從計算出的候選端口開(kāi)始線(xiàn)性搜索整個(gè)端口空間即可,由于全局計數器是遞增的,所以除非使用bind占據了某個(gè)端口,一般都會(huì )很快找到可用端口號,最多搜索幾個(gè)就能找到。算法如下所示:
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <pthread.h>  
  4.   
  5. #define LOW     10000  
  6. #define HIGH    65535  
  7.   
  8. static unsigned int hint = 0;  
  9.   
  10. //端口分配函數  
  11. //base:一個(gè)(源IP,目標IP,目標端口)三元組的hash值  
  12. int get_local_port(int base )  
  13. {  
  14.         unsigned int i,j,port, remaining;  
  15.         unsigned int offset = hint + base;  
  16.         remaining = (HIGH - LOW) + 1;  
  17.   
  18.         for (i = 1; i <= remaining; i++) {  
  19.                 int port_ok = 0;  
  20.                 port = LOW + (i + offset) % remaining;  
  21.                 //判斷該端口是否可用,由于僅四元組唯一即可接受,現在假設:  
  22.                 //所有的端口均已經(jīng)安全釋放。  
  23.                 port_ok = 1;  
  24.                 if (port_ok) {  
  25.                         break;  
  26.                 }  
  27.         }  
  28.         //越過(guò)你排除的那幾個(gè)(那些!)  
  29.         hint += i;  
  30.         return port;  
  31. }  
  32.   
  33. //hint遞增函數  
  34. int inc_hint(int value)  
  35. {  
  36.         hint += value;  
  37. }  
  38.   
  39. //分配端口線(xiàn)程  
  40. void *func(void *arg)  
  41. {  
  42.         while(1) {  
  43.                 int port = get_local_port(0);  
  44.                 printf(" %d \n", port);  
  45.                 sleep(1);  
  46.         }  
  47. }  
  48.   
  49. //hint遞增線(xiàn)程  
  50. void *func_others(void *arg)  
  51. {  
  52.         while (1) {  
  53.                 int rnd = random();  
  54.                 //其它的線(xiàn)程選擇源端口的時(shí)候,由于使用不同的(源IP,目標IP,目標端口)  
  55.                 //不會(huì )有任何沖突,因此只模擬遞增hint即可。  
  56.                 inc_hint (1);  
  57.                 sleep(1);  
  58.         }  
  59. }  
  60.   
  61. //main函數  
  62. int main(int argc, char **argv)  
  63. {  
  64.   
  65.         pthread_t id[20] = {0};  
  66.         int i = 0, ret = 0;  
  67.         //一個(gè)線(xiàn)程不斷分配端口  
  68.         ret = pthread_create(&id[0], NULL, (void*)func, NULL);  
  69.         if (ret) {  
  70.                 printf("Create pthread error!/n");  
  71.                 return 1;  
  72.         }  
  73.         //N個(gè)線(xiàn)程模擬其它的端口分配,僅僅遞增hint  
  74.         for (i = 1; i < 20; i++) {  
  75.                 ret = pthread_create(&id[i], NULL, (void*)func_others, NULL);  
  76.                 if (ret) {  
  77.                         printf("Create pthread error!/n");  
  78.                         return 1;  
  79.                 }  
  80.         }  
  81.         for (i = 0; i < 20; i++) {  
  82.                 pthread_join(id[i], NULL);  
  83.         }  
  84.         return 0;  
  85. }  

關(guān)鍵點(diǎn)在于,三元組已經(jīng)確定,剩下的就是根據不同的三元組獨立遞增端口,效果就是同樣三元組的端口都聚集在一起,在無(wú)需鏈表的情況下高效判斷!

附:關(guān)于列維搜索

列維模型其實(shí)是一種概率分布模型,和泊松分布大大不同!它更多的體現在一種“生長(cháng),聚集”效應上。通俗來(lái)講就是,首先隨機確定一個(gè)點(diǎn),然后在該點(diǎn)附近進(jìn)行遍歷搜索,成功后則加入,達到閥值后依然沒(méi)有找到則退出,再次隨機生成一個(gè)點(diǎn),在該點(diǎn)附近搜索,以此類(lèi)推。這種模型有很精確的數學(xué)證明。如果對數學(xué)望而卻步,可以從生活中體會(huì )。剛畢業(yè)不久的人,可能會(huì )留在一個(gè)城市工作,兩三年內換了N份工作,接下來(lái)突然到達一個(gè)陌生的城市,從新開(kāi)始...這就是列維模型!本質(zhì)上講,整個(gè)人類(lèi)文明都是遵循列維模型,一開(kāi)始原始人從來(lái)不知道哪里適合居住,也不知道自己要到哪里去,只是漂泊蕩漾,但是過(guò)了千百萬(wàn)年以后,我們發(fā)現人類(lèi)的分布并不是平均的,也就是說(shuō),有些地方發(fā)展成了大都市,有些地方依然沒(méi)有人煙,這難道說(shuō)發(fā)展成都市的地方自然條件優(yōu)于沒(méi)有人煙的地方嗎?非也!列維模型在起作用,它正如莫菲法則一樣是個(gè)真理!

       列維模型一直都在主宰著(zhù)我們,并且工作的很好,由于列維模型,我們現在擁有了典型的幾個(gè)不錯的國際化大都市...列維模型正如磁石一樣在發(fā)揮著(zhù)作用。它本質(zhì)上就是要把同類(lèi)同質(zhì)的東西聚集在一起!Linux在bind的時(shí)候分配端口正是使用這種列維搜索方式。列維模型天生具備一個(gè)閥值,即,在由于列維模型聚集在一起的東西超過(guò)閥值后,將不再聚集,而是選擇“長(cháng)跳”,即隨機到達一個(gè)比較遠的地方重新開(kāi)始聚集!列維模型總結起來(lái)就是,局部搜索,達到范圍閥值后,到一個(gè)很遠但是隨機的地方重新開(kāi)始局部搜索!如下圖所示:


本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
字節一面:TCP 和 UDP 可以使用同一個(gè)端口嗎?
【原創(chuàng )】銳捷交換機安全配置總結
華為交換機MAC地址與端口綁定
自架設CDN服務(wù)器——智能DNS解析及Squid集群 大型網(wǎng)站加速解決方案 –
MongoDB最佳安全實(shí)踐
沒(méi)有公網(wǎng)IP的機器如何能被外網(wǎng)訪(fǎng)問(wèn)
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久