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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux socket跨局域网聊天和文件传输

發布時間:2023/12/18 linux 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux socket跨局域网聊天和文件传输 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一直想寫一個跨局域網聊天和文件傳輸,以及視頻聊天的軟件,這兩天剛好閑著沒啥事就把代碼寫完了,代碼已經上傳至github:https://github.com/vinllen/chat

其實之前想法P2P模式,P2P的話必須穿透NAT,現在的NAT有4種模式:

  • 完全圓錐型NAT
  • 受限圓錐型NAT
  • 端口受限圓錐型NAT
  • 對稱NAT(雙向NAT)
  • 維基百科給出的定義如下:

    • 1.Full cone NAT,亦即著名的一對一(one-to-one)NAT

    一旦一個內部地址(iAddr:port1)映射到外部地址(eAddr:port2),所有發自iAddr:port1的包都經由eAddr:port2向外發送。任意外部主機都能通過給eAddr:port2發包到達iAddr:port1


    • 2.Address-Restricted cone NAT

    一旦一個內部地址(iAddr:port1)映射到外部地址(eAddr:port2),所有發自iAddr:port1的包都經由eAddr:port2向外發送。任意外部主機(hostAddr:any)都能通過給eAddr:port2發包到達iAddr:port1的前提是:iAddr:port1之前發送過包到hostAddr:any. "any"也就是說端口不受限制



    • 3.Port-Restricted cone NAT
    類似受限制錐形NAT(Restricted cone NAT),但是還有端口限制。

    一旦一個內部地址(iAddr:port1)映射到外部地址(eAddr:port2),所有發自iAddr:port1的包都經由eAddr:port2向外發送。一個外部主機(hostAddr:port3)能夠發包到達iAddr:port1的前提是:iAddr:port1之前發送過包到hostAddr:port3.



    • 4.Symmetric NAT(對稱NAT)
    每一個來自相同內部IP與端口,到一個特定目的地地址和端口的請求,都映射到一個獨特的外部IP地址和端口。同一內部IP與端口發到不同的目的地和端口的信息包,都使用不同的映射
    只有曾經收到過內部主機封包的外部主機,才能夠把封包發回



    對于第1種特別簡單,因為端口存在映射,只要把包發網出口路由的端口即可,路由會幫你轉發

    對于第2,3種情況,可以采用如下辦法(內容來自該博客:點擊打開鏈接):

    假設網絡模型如下:


    限制性錐NAT 和端口限制性錐NAT (簡稱限制性NAT ),穿透限制性錐NAT 會丟棄它未知的源地址發向內部主機的數據包。所以如果現在ClientA-1 直接發送UDP 數據包到ClientB-1 ,那么數據包將會被NAT-B 無情的丟棄。所以采用下面的方法來建立ClientA-1 和ClientB-1 之間的通信。

    • 1 .ClientA-1 (202.103.142.29:5000 )發送數據包給Server ,請求和ClientB-1 (221.10.145.84:6000 )通信。
    • 2. Server 將ClientA-1 的地址和端口(202.103.142.29:5000 )發送給ClientB-1 ,告訴ClientB-1 ,ClientA-1 想和它通信。
    • 3. ClientB-1 向ClientA-1 (202.103.142.29:5000 )發送UDP 數據包,當然這個包在到達NAT-A 的時候,還是會被丟棄,這并不是關鍵的,因為發送這個UDP 包只是為了讓NAT-B 記住這次通信的目的地址:端口號,當下次以這個地址和端口為源的數據到達的時候就不會被NAT-B 丟棄,這樣就在NAT-B 上打了一個從ClientB-1 到ClientA-1 的孔。
    • 4. 為了讓ClientA-1 知道什么時候才可以向ClientB-1 發送數據,所以ClientB-1 在向ClientA-1 (202.103.142.29:5000 )打孔之后還要向Server 發送一個消息,告訴Server 它已經準備好了。
    • 5. Server 發送一個消息給ClientA-1 ,內容為:ClientB-1 已經準備好了,你可以向ClientB-1 發送消息了。
    • 6. ClientA-1 向ClientB-1 發送UDP 數據包。這個數據包不會被NAT-B 丟棄,以后ClientB-1 向ClientA-1 發送的數據包也不會被ClientA-1 丟棄,因為NAT-A 已經知道是ClientA-1 首先發起的通信。至此,ClientA-1 和ClientB-1 就可以進行通信了。
    對于第4種情況,oh no,太難了,需要猜測端口號(博客地址:點擊打開鏈接): 上面討論的都是怎樣穿透錐(Cone )NAT ,對稱NAT 和錐NAT 很不一樣。對于對稱NAT ,當一個私網內主機和外部多個不同主機通信時,對稱NAT并不會像錐(Cone ,全錐,限制性錐,端口限制性錐)NAT那樣分配同一個端口。而是會新建立一個Session ,重新分配一個端口。參考上面穿透限制性錐NAT 的過程,在步驟3 時:ClientB-1 (221.10.145.84: ?)向ClientA-1 打孔的時候,對稱NAT 將給ClientB-1 重新分配一個端口號,而這個端口號對于Server 、ClientB-1 、ClientA-1 來說都是未知的。同樣, ClientA-1 根本不會收到這個消息,同時在步驟4 ,ClientB-1 發送給Server 的通知消息中,ClientB-1 的socket 依舊是(221.10.145.84:6000 )。而且,在步驟6 時:ClientA-1 向它所知道但錯誤的ClientB-1 發送數據包時,NAT-1 也會重新給ClientA-1 分配端口號。所以,穿透對稱NAT 的機會很小。下面是兩種有可能穿透對稱NAT 的策略。
    1.同時開放TCP ( Simultaneous TCP open )策略
    如果一個 對稱 NAT 接收到一個來自 本地 私有網 絡 外面的 TCP SYN 包, 這 個包想 發 起一個 “ 引入” 的 TCP 連 接,一般來 說 , NAT 會拒 絕這 個 連 接 請 求并扔掉 這 個 SYN 包,或者回送一個TCP RST (connection reset ,重建 連 接)包 給請 求方。但是,有一 種 情況 卻會接受這個“引入”連接。
    RFC 規定:對于對稱NAT , 當 這 個接收到的 SYN 包中的源IP 地址 : 端口、目 標 IP 地址 : 端口都與NAT 登 記 的一個已 經 激活的 TCP 會 話 中的地址信息相符 時 , NAT 將會放行 這 個 SYN 包。 需要 特 別 指出 的是:怎樣才是一個已經激活的TCP 連接?除了真正已經建立完成的TCP 連接外,RFC 規范指出: 如果 NAT 恰好看到一個 剛剛發 送出去的一個 SYN 包和 隨之 接收到的SYN 包中的地址 :端口 信息相符合的 話 ,那 么 NAT 將會 認為這 個 TCP 連 接已 經 被激活,并將允 許這 個方向的 SYN 包 進 入 NAT 內部。 同時開放TCP 策略就是利用這個時機來建立連接的。
    如果 Client A -1 和 Client B -1 能 夠 彼此正確的 預 知 對 方的 NAT 將會 給 下一個 TCP 連 接分配的公網 TCP 端口,并且兩個客 戶 端能 夠 同 時 地 發 起一 個面向對方的 “ 外出 ” 的 TCP 連 接 請求 ,并在 對 方的 SYN 包到達之前,自己 剛發 送出去的 SYN 包都能 順 利的穿 過 自己的 NAT 的 話 ,一條端 對 端的 TCP 連 接就 能 成功地建立了 。
    2.UDP 端口猜測策略
    同時開放TCP 策略非常依賴于猜測對方的下一個端口,而且強烈依賴于發送連接請求的時機,而且還有網絡的不確定性,所以能夠建立的機會很小,即使Server 充當同步時鐘的角色。下面是一種通過UDP 穿透的方法,由于UDP 不需要建立連接,所以也就不需要考慮“同時開放”的問題。
    為了介紹ClientB-1 的詭計,先介紹一下STUN 協議。STUN (Simple Traversal of UDP Through NATs )協議是一個輕量級協議,用來探測被NAT 映射后的地址:端口。STUN 采用C/S 結構,需要探測自己被NAT 轉換后的地址:端口的Client 向Server 發送請求,Server 返回Client 轉換后的地址:端口。
    參考4.2 節中穿透NAT 的步驟2 ,當ClientB-1 收到Server 發送給它的消息后,ClientB-1 即打開3 個socket 。socket-0 向STUN Server 發送請求,收到回復后,假設得知它被轉換后的地址:端口( 221.10.145.84:600 5 ),socket-1 向ClientA-1 發送一個UDP 包,socket-2 再次向另一個STUN Server 發送請求,假設得到它被轉換后的地址:端口( 221.10.145.84:60 20 )。通常,對稱NAT 分配端口有兩種策略,一種是按順序增加,一種是隨機分配。如果這里對稱NAT 使用順序增加策略,那么,ClientB-1 將兩次收到的地址:端口發送給Server 后,Server 就可以通知ClientA-1 在這個端口范圍內猜測剛才ClientB-1 發送給它的socket-1 中被NAT 映射后的地址:端口,ClientA-1 很有可能在孔有效期內成功猜測到端口號,從而和ClientB-1 成功通信。


    /************************************華麗分割線**********************************************************/ 以上內容大部分參考維基百科和chengweiv5的博客,我自己也寫了代碼,嘗試用第二種方式去穿透我們學校所在的NAT,結果悲劇了,找了好幾天的問題也沒找出來到底是代碼的原因呢還是NAT限制為第4種的原因呢。 But項目不能這么擱淺了。我采用了另外一條曲線救國的路線,就跟現在QQ模式一樣,用中轉服務器進行消息轉發實現。 1.首先搞了一臺具有公網ip的服務器 2.配置好環境后(比如iptables等),把服務器代碼放置服務器,運行 3.客戶端連接后就可以發送文件和聊天了 That's all,就這么簡單。 唯一需要說明的就是發送文件時我調用的是sendfile的系統調用,接收文件調用了Pat Patterson的包裹函數:利用splice接收文件,理論上這兩個函數是直接在內核態進行文件傳遞,而不用在內核態和普通態進行數據的拷貝,減少時間。我測試了一下,對幾M大小的文件都沒問題,不過貌似文件大了貌似傳不動了,目測sendfile有大小限制。。。這個就之后再改改了。 最后一點,本來還要實現視頻傳輸的,我的想法就是用opencv調用本地攝像頭,然后把圖片按每秒固定幀數截下來,按文件方法傳輸,再在對端對圖片進行拼接成視頻。后來感覺有點麻煩,最后上網一查,果然我做的部分就是重造輪子的活,現在直接都有現成的文件傳輸協議。這部分也等以后有時間再去完善吧。 Finally,?如果大家有誰有想法,可以和我交流交流,一起學習進步

    總結

    以上是生活随笔為你收集整理的Linux socket跨局域网聊天和文件传输的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。