Python http server IPv6

今天準備測試一下IPv6皿伺,習慣性地使用Python的http.server模塊寝贡,意外的發(fā)現(xiàn)它不支持IPv6悼吱。在StackOverflow上有人說沸停,把HttpServeraddress_family改成AF_INET6即可堰酿。于是瀏覽了一下/usr/lib/python3.6/http/server.py代碼疾宏,說干就干。

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--cgi', action='store_true',
                       help='Run as CGI Server')
    parser.add_argument('--ipv6', '-6', action='store_true',
                        help='Set address family to IPv6')
    parser.add_argument('--bind', '-b', default='', metavar='ADDRESS',
                        help='Specify alternate bind address '
                             '[default: all interfaces]')
    parser.add_argument('port', action='store',
                        default=8000, type=int,
                        nargs='?',
                        help='Specify alternate port [default: 8000]')
    args = parser.parse_args()
    if args.cgi:
        handler_class = CGIHTTPRequestHandler
    else:
        handler_class = SimpleHTTPRequestHandler
    server_class=HTTPServer

    if args.ipv6:
        server_class = type("HTTPServerV6", (HTTPServer,),
                            dict(address_family=socket.AF_INET6))
    else:
        server_class = HTTPServer

    test(HandlerClass=handler_class, ServerClass=server_class, port=args.port, bind=args.bind)

加了一行parser.add_argument('--ipv6', '-6', action='store_true', help='Set address family to IPv6')來解析IPv6參數(shù)触创,許多命令行工具都用了這種方式坎藐,例如ping -6, curl -6, telnet -6等。
使用type函數(shù)哼绑,動態(tài)創(chuàng)建一個新的類HTTPServerV6岩馍,其address_family設置成AF_INET6。這種寫法可以不用顯式繼承而得到一個新的派生類抖韩,不會修改原類的屬性蛀恩。
修改完代碼并保存,執(zhí)行python -m http.server -6 -b ::帽蝶,成功監(jiān)聽IPv6地址赦肋,使用netstat -lpt可以查看。不加-6參數(shù)程序還是原來的用法励稳,堪稱完美佃乘。

tcp6       0      0 [::]:8000               [::]:*                  LISTEN      7252/python3        

興致勃勃準備去Github給Python提PR,發(fā)現(xiàn)master上的代碼是這樣的驹尼,原來Python 3.8開始趣避,http.server模塊就已經(jīng)支持IPv6了。

if __name__ == '__main__':
    import argparse

    parser = argparse.ArgumentParser()
    parser.add_argument('--cgi', action='store_true',
                       help='Run as CGI Server')
    parser.add_argument('--bind', '-b', metavar='ADDRESS',
                        help='Specify alternate bind address '
                             '[default: all interfaces]')
    parser.add_argument('--directory', '-d', default=os.getcwd(),
                        help='Specify alternative directory '
                        '[default:current directory]')
    parser.add_argument('port', action='store',
                        default=8000, type=int,
                        nargs='?',
                        help='Specify alternate port [default: 8000]')
    args = parser.parse_args()
    if args.cgi:
        handler_class = CGIHTTPRequestHandler
    else:
        handler_class = partial(SimpleHTTPRequestHandler,
                                directory=args.directory)

    # ensure dual-stack is not disabled; ref #38907
    class DualStackServer(ThreadingHTTPServer):
        def server_bind(self):
            # suppress exception when protocol is IPv4
            with contextlib.suppress(Exception):
                self.socket.setsockopt(
                    socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0)
            return super().server_bind()

    test(
        HandlerClass=handler_class,
        ServerClass=DualStackServer,
        port=args.port,
        bind=args.bind,
    )

它使用了雙棧套接字技術新翎,在Linux上默認啟用雙棧套接字程帕,只需要創(chuàng)建一個基于IPv6的TCP套接字,即可同時支持IPv4和IPv6地啰。如果系統(tǒng)設置了IPV6_V6ONLY選項愁拭,即/proc/sys/net/ipv6/bindv6only不為0,則需要使用setsockopt取消這個選項才能啟用雙棧套接字亏吝。

sock = socket(AF_INET6, SOCK_STREAM, 0);
//enable dual stack if disabled
//int opt = 0;
//setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt));
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末岭埠,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌惜论,老刑警劉巖许赃,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異馆类,居然都是意外死亡混聊,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進店門乾巧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來句喜,“玉大人,你說我怎么就攤上這事卧抗√倮模” “怎么了?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵社裆,是天一觀的道長拙绊。 經(jīng)常有香客問我,道長泳秀,這世上最難降的妖魔是什么标沪? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮嗜傅,結果婚禮上金句,老公的妹妹穿的比我還像新娘。我一直安慰自己吕嘀,他們只是感情好违寞,可當我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著偶房,像睡著了一般趁曼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上棕洋,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天挡闰,我揣著相機與錄音,去河邊找鬼掰盘。 笑死摄悯,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的愧捕。 我是一名探鬼主播奢驯,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼次绘!你這毒婦竟也來了叨橱?” 一聲冷哼從身側響起典蜕,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤断盛,失蹤者是張志新(化名)和其女友劉穎罗洗,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體钢猛,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡伙菜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了命迈。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片贩绕。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖壶愤,靈堂內(nèi)的尸體忽然破棺而出淑倾,到底是詐尸還是另有隱情,我是刑警寧澤征椒,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布娇哆,位于F島的核電站,受9級特大地震影響勃救,放射性物質(zhì)發(fā)生泄漏碍讨。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一蒙秒、第九天 我趴在偏房一處隱蔽的房頂上張望勃黍。 院中可真熱鬧,春花似錦晕讲、人聲如沸覆获。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽弄息。三九已至,卻和暖如春净捅,著一層夾襖步出監(jiān)牢的瞬間疑枯,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工蛔六, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留荆永,地道東北人。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓国章,卻偏偏與公主長得像具钥,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子液兽,可洞房花燭夜當晚...
    茶點故事閱讀 43,490評論 2 348