天天看點

在bash中建立網絡連接配接

近期在工作中碰到一個問題,需要建立一個TCP(或者UDP也可以)連接配接到另一台機器,隻需要連接配接某個自定義的端口一下即可,連接配接後馬上斷開,不用發送任何資料,以此作為一種“心跳”的實作。實作這個需要編寫一個TCP小程式放到心跳發起的機器上然後循環執行它。當然這個小程式越簡單越好,于是就想到用python,然而由于機器上的軟體已經被裁減了,根本就沒有對python的支援,如果為此“安裝”一個python,能預見的就是遇到一系列的庫依賴問題,最終陷入一個泥潭。如果真這樣,我還不如直接用C寫一個心跳發送程式呢...最終的方案是使用telnet:

echo ^]quit |telnet 192.168.2.2 1234

這樣就可以連接配接上之後立馬斷開了,可以使用,于是就采用了。很顯然對端需要有一個接收程式,使用nc再簡單不過了:

nc -l -p 1234

完事後,就這個問題又進一步思考了一下。萬一連telnet也沒有該怎麼辦?這次之是以用了telnet,那是湊巧了!于是就想如果能用shell内建的指令建立TCP連接配接該多好。google之,man之,終于發現了一個bash内建的檔案:/dev/tcp[or UDP]/[IP or HostName]/port

隻要打開這個檔案,就能建立一個TCP或者UDP連接配接到[IP or HostName]的port端口,現在的問題是如何打開這個檔案。想要打開這個檔案,你一定要用bash内建指令打開,因為隻有bash可以識别/dev/tcp...否則如果你用cat打開的話,由于cat不能識别它,就要真的去/dev路徑下去尋找了,結果可想而知:no such file...

    使用exec這個内建指令可以完成這個工作,exec不附帶任何command以替換目前bash,而僅僅是為了打開上述的tcp檔案,然後将之定向到一個空閑的檔案描述符,這樣我們就可以操作該檔案描述符了:

1.首先重定向,建立連接配接:

exec 6>/dev/tcp/192.168.2.2/1234

2.然後關閉:

exec 6>&-

3.其它

在關閉之前,你可以使用下面的指令來向該連接配接發送資料:

echo -e "$data" >&6

在關閉之前,你可以使用下面的指令來讀取該連接配接傳回的資料:

cat <&6

以上就是使用bash内建指令exec以及内建檔案名/dev/$proto/$address/$port進行網絡通信的方法。美中不足的地方在于bash沒有對應的檔案産生TCP/UDP伺服器,如果萬一系統中沒有nc,沒有python,你就不得不動用C了,編譯,複制到系統,萬一出錯或者庫不比對,就要重新編譯,連結。但是由于bash的源碼可獲得,是以修改它就可以了。在動手之前首先要設計好接口。以下僅僅以TCP為例。對于用戶端而言,bash的/dev/tcp/接口設計的很好,于是我們可以仿造該接口設計一個新的TCP伺服器的接口用于偵聽某一個端口:

/dev/tcp-server/$IP/$PORT

在bash中,隻要重定向這個檔案就打開一個偵聽TCP,現在問題是如何接受用戶端的連接配接并且提供服務,而且這一切還必須内置于bash,我們可以采用“讀取”該TCP服務檔案描述符的方式,其内容是一個工作套接字的檔案描述符,或者用tail也可以:

1.建立一個偵聽套接字:

exec 6>/dev/tcp-server/192.168.2.2/1234

2.等待用戶端連接配接:

傳回8

3.提供服務:

cat <&8

...

echo -e "response" >&8

4.主動斷開連接配接:

exec 8>&-

5.停止服務:

至于實作,對着已有的用戶端實作比葫蘆畫瓢即可,這個不重要,重要的是如何使得接口更容易被使用,如果還沒有nc友善,那麼做這個就沒有意義了。實際上你不能指望該方式能提供多麼複雜的服務,它基本上就是一個調試網絡的工具而已,這也許就是bash為何隻實作了client而沒有實作server的原因吧。

 本文轉自 dog250 51CTO部落格,原文連結:http://blog.51cto.com/dog250/1268984