<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    聶永的博客

    記錄工作/學習的點點滴滴。

    100萬并發連接服務器筆記之處理端口數量受限問題

    第二個遇到的問題:端口數量受限

    一般來說,單獨對外提供請求的服務不用考慮端口數量問題,監聽某一個端口即可。但是向提供代理服務器,就不得不考慮端口數量受限問題了。當前的1M并發連接測試,也需要在客戶端突破6萬可用端口的限制。

    單機端口上限為65536

    端口為16進制,那么2的16次方值為65536,在linux系統里面,1024以下端口都是超級管理員用戶(如root)才可以使用,普通用戶只能使用大于1024的端口值。
    系統提供了默認的端口范圍:

    cat /proc/sys/net/ipv4/ip_local_port_range
    32768 61000

    大概也就是共61000-32768=28232個端口可以使用,單個IP對外只能發送28232個TCP請求。
    以管理員身份,把端口的范圍區間增到最大:

    echo "1024 65535"> /proc/sys/net/ipv4/ip_local_port_range

    現在有64511個端口可用.
    以上做法只是臨時,系統下次重啟,會還原。 更為穩妥的做法是修改/etc/sysctl.conf文件,增加一行內容

    net.ipv4.ip_local_port_range= 1024 65535

    保存,然后使之生效:

    sysctl -p

    現在可以使用的端口達到64510個(假設系統所有運行的服務器是沒有占用大于1024的端口的,較為純凈的centos系統可以做到),要想達到50萬請求,還得再想辦法。

    增加IP地址

    一般假設本機網卡名稱為 eth0,那么手動再添加幾個虛擬的IP:

    ifconfig eth0:1 192.168.190.151
    ifconfig eth0:2 192.168.190.152 ......

    或者偷懶一些:

    for i in `seq 1 9`; do ifconfig eth0:$i 192.168.190.15$i up ; done

    這些虛擬的IP地址,一旦重啟,或者 service network restart 就會丟失。

    為了模擬較為真實環境,在測試端,手動再次添加9個vmware虛擬機網卡,每一個網卡固定一個IP地址,這樣省去每次重啟都要重新設置的麻煩。

    192.168.190.134
    192.168.190.143
    192.168.190.144
    192.168.190.145
    192.168.190.146
    192.168.190.147
    192.168.190.148
    192.168.190.149
    192.168.190.150
    192.168.190.151

    在server服務器端,手動添加橋接網卡和NAT方式網卡

    192.168.190.230
    192.168.190.240
    10.95.20.250
    

    要求測試端和服務器端彼此雙方都是可以ping通。

    網絡四元組/網絡五元組

    四元組是指的是

    {源IP地址,源端口,目的IP地址,目的端口}

    五元組指的是(多了協議)

    {源IP地址,目的IP地址,協議號,源端口,目的端口}

    在《UNIX網絡編程卷1:套接字聯網API(第3版)》一書中,是這樣解釋:
    一個TCP連接的套接字對(socket pari)是一個定義該連接的兩個端點的四元組,即本地IP地址、本地TCP端口號、外地IP地址、外地TCP端口號。套接字對唯一標識一個網絡上的每個TCP連接。

    ......

    標識每個端點的兩個值(IP地址和端口號)通常稱為一個套接字。

    以下以四元組為準。在測試端四元組可以這樣認為:

    {本機IP地址,本機端口,目的IP地址,目的端口}

    請求的IP地址和目的端口基本上是固定的,不會變化,那么只能從本機IP地址和本機端口上考慮,端口的范圍一旦指定了,那么增加IP地址,可以增加對外發出的請求數量。假設系統可以使用的端口范圍已經如上所設,那么可以使用的大致端口為64000個,系統添加了10個IP地址,那么可以對外發出的數量為 64000 * 10 = 640000,數量很可觀。

    只有{源IP地址,源端口}確定對外TCP請求數量

    經測試,四元組里面,只有{源IP地址,源端口}才能夠確定對外發出請求的數量,跟{目的IP地址,目的端口}無關。

    測試環境

    在server端,并且啟動./server兩次,分別綁定8000端口和9000端口

    ./server -p 8000
    ./server -p 9000
    

    本機IP、端口綁定測試程序

    這里寫一個簡單的測試綁定本機IP地址和指定端口的客戶端測試程序。

    可以看到libevent-*/include/event2/http.h內置了對綁定本地IP地址的支持:

    /** sets the ip address from which http connections are made */
    void evhttp_connection_set_local_address(struct evhttp_connection *evcon,
    const char *address);
    

    不用擔心端口,系統自動自動隨機挑選,除非需要特別指定:

    /** sets the local port from which http connections are made */
    void evhttp_connection_set_local_port(struct evhttp_connection *evcon,
    ev_uint16_t port);
    

    編譯

    gcc -o client3 client3.c -levent
    

    client3運行參數為

    • -h 遠程主機IP地址
    • -p 遠程主機端口
    • -c 本機指定的IP地址(必須可用)
    • -o 本機指定的端口(必須可用)

    測試用例,本機指定同樣的IP地址和端口,但遠程主機和IP不一樣.
    在一個測試端打開一個終端窗口1,切換到 client3對應位置

    ./client3 -h 192.168.190.230 -p 8000 -c 192.168.190.148 -o 4000
    

    輸出為

    remote host is 192.168.190.230
    remote port is 8000
    local ip is 192.168.190.148
    local port is 4000
    >Chunks: 1 Bytes: 505
    

    再打開一個測試端終端窗口2,執行:

    ./client3 -h 192.168.190.240 -p 9000 -c 192.168.190.148 -o 4000
    

    窗口2程序,無法執行,自動退出。
    接著在窗口2終端繼續輸入:

    ./client3 -h 192.168.190.230 -p 8000 -c 192.168.190.148 -o 4001
    

    注意,和窗口1相比,僅僅改變了端口號為4001。但執行結果,和端口1輸出一模一樣,在等待接收數據,沒有自動退出。

    剩下的,無論怎么組合,怎么折騰,只要一對{本機IP,本機端口}被占用,也就意味著對應一個具體的文件句柄,那么其它程序將不能夠再次使用。

    Java怎么綁定本地IP地址?

    java綁定就很簡單,但有些限制,不夠靈活,單純從源碼中看不出來,api doc可以告訴我們一些事情。 打開JDKAPI1_6zhCN.CHM,查看InetSocketAddress類的構造函數說明:

    public InetSocketAddress(InetAddress addr, int port)
    根據 IP 地址和端口號創建套接字地址。 有效端口值介于 0 和 65535 之間。端口號 zero 允許系統在 bind 操作中挑選暫時的端口。

    null 地址將分配通配符 地址。

    參數:
    addr - IP 地址
    port - 端口號
    拋出:
    IllegalArgumentException - 如果 port 參數超出有效端口值的指定范圍。


    public InetSocketAddress(String hostname, int port)
    根據主機名和端口號創建套接字地址。
    嘗試將主機名解析為 InetAddress。如果嘗試失敗,則將地址標記為未解析。

    如果存在安全管理器,則將主機名用作參數調用其 checkConnect 方法,以檢查解析它的權限。這可能會導致 SecurityException 異常。

    有效端口值介于 0 和 65535 之間。端口號 zero 允許系統在 bind 操作中挑選暫時的端口。

    參數: hostname - 主機名
    port - 端口號
    拋出:
    IllegalArgumentException - 如果 port 參數超出有效端口值的范圍,或者主機名參數為 null。
    SecurityException - 如果存在安全管理器,但拒絕解析主機名的權限。
    另請參見:
    isUnresolved()

    InetSocketAddress的兩個構造函數都支持,看情況使用。注意int port傳遞值為0,即可做到系統隨機挑選端口。追蹤一下源代碼,發現最終調用

    private native void socketBind(InetAddress address, int port) throws IOException;
    

    如何查看socketBind的原始C代碼,我就不清楚了,您若知曉,希望指教一下。 構造一個InetSocketAddress對象:

    SocketAddress localSocketAddr = new InetSocketAddress("192.168.190.143", 0);
    

    然后傳遞給需要位置即可。諸如使用netty連接到某個服務器上,在connect時指定遠方地址,以及本機地址

    ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress) Attempts a new connection with the specified remoteAddress and the specified localAddress.

    Netty 客戶端連接API見:

    Linux支持綁定本機IP、端口原理

    說是原理,有些牽強,因為linux C提供了如何綁定函數,框架或者高級語言再怎么封裝,在linux平臺下面,需要這么調用:

    struct sockaddr_in clnt_addr;
    ....
    clnt_addr.sin_family = AF_INET;
    clnt_addr.sin_addr.s_addr = INADDR_ANY; //綁定本機IP地址
    clnt_addr.sin_port = htons(33333); //綁定本機端口
    if (bind(sockfd, (struct sockaddr *) &clnt_addr,
    sizeof(clnt_addr)) < 0) error("ERROR on binding");
    if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) error("ERROR connecting");
    .......
    

    構造一個clnt_addr結構體,本地IP或者端口賦值,在connect之前,先bind,就這么簡單。

    更完整例子,可以參考 http://stackoverflow.com/questions/4852256/need-a-complete-snippet-example-of-binding-tcp-client-socket

    有關端口的更詳細解釋,請參考《UNIX網絡編程卷1:套接字聯網API(第3版)》2.9節 端口號部分。

     

    有關端口的問題,到此為止,下一篇,回到測試。

    posted on 2013-04-09 17:26 nieyong 閱讀(18428) 評論(0)  編輯  收藏 所屬分類: C1M

    公告

    所有文章皆為原創,若轉載請標明出處,謝謝~

    新浪微博,歡迎關注:

    導航

    <2013年4月>
    31123456
    78910111213
    14151617181920
    21222324252627
    2829301234
    567891011

    統計

    常用鏈接

    留言簿(58)

    隨筆分類(130)

    隨筆檔案(151)

    個人收藏

    最新隨筆

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 久久无码av亚洲精品色午夜| 亚洲色偷偷综合亚洲av78| 亚洲人妻av伦理| 亚洲午夜国产精品无码老牛影视| 亚洲色欲久久久综合网东京热| 亚洲av不卡一区二区三区 | 久久久久成人精品免费播放动漫| 99视频在线精品免费| 噼里啪啦免费观看高清动漫4 | 国产在线观看免费观看不卡 | 在线播放亚洲第一字幕| 亚洲网站在线免费观看| 在线91精品亚洲网站精品成人| 国产免费无码AV片在线观看不卡 | 99久热只有精品视频免费看| 成年女人永久免费观看片| 亚洲无线观看国产精品| 337P日本欧洲亚洲大胆艺术图| 久久99热精品免费观看动漫| 免费国产在线观看老王影院| 亚洲国产成人精品无码区在线秒播 | 日本最新免费网站| 亚洲高清偷拍一区二区三区 | 亚洲五月六月丁香激情| 久久久久免费视频| 可以免费观看的一级毛片| 亚洲高清中文字幕免费| 中文字幕无码播放免费| 亚洲色图.com| 亚洲一级毛片免费观看| 亚洲成人一级电影| 国产大片免费网站不卡美女 | 国产精品亚洲美女久久久| 无码天堂亚洲国产AV| 亚洲日韩VA无码中文字幕 | 成年女人看片免费视频播放器| 亚洲高清日韩精品第一区| 中文字幕乱码免费视频| 亚洲狠狠成人综合网| 日本视频免费在线| 黄页网址大全免费观看12网站|