bash socket communication
2007-02-07 17:03
有時在外面跑來跑去 會需要知道目前對外連線的 ip
所以我放了個簡單的 page 在 http://outian.net/
直接用 browser 連就可以看到自己 ip ...
但有時懶得開、或根本沒 browser 可用時 , 可以用一些指令達到一樣的效果
1. nc
$ printf "GET / HTTP/1.0\n\n" | nc outian.net 80
HTTP/1.1 200 OK
Date: Tue, 30 Jan 2007 07:54:28 GMT
Server: Apache
Vary: Accept-Encoding,User-Agent
Content-Length: 23
Connection: close
Content-Type: text/html
Your IP is xxx.xxx.xxx.xxx
2. telnet
$ telnet outian.net 80 [Enter]
Trying 140.136.152.115...
Connected to outian.net (140.136.152.115).
Escape character is ‘^]'.
GET / HTTP/1.0 [Enter]
[Enter]
....(同 1. 的結果, 略)
Connection closed by foreign host.
3. wget
$ wget -q -O /dev/stdout http://outian.net/
Your IP is xxx.xxx.xxx.xxx
4. bash
偶然間逛到 其實除了 telnet、nc 等工具外
bash 本身也可以做簡單的 socket communication
應用1 - 簡單的顯示完整 HTTP Message
$ exec 5<> /dev/tcp/outian.net/80
$ printf "GET / HTTP/1.0\n\n" >& 5
$ cat <& 5
....(同 1. 的結果, 略)
$ exec 5<&-
(可以用 ; 隔開 一行執行完 , 但 BBS 的畫面放不下 ... so 拆開執行)
這些用法一般人比較少用到, 所以稍微說明一下 ...
在 linux 的 bash 裡 (在其他 os 裡似乎不會動),
可以開啟 /dev/tcp/host/port 對該 host:port 作 tcp communication
也可以對 /dev/udp/host/port 作 udp ...
所以一開始先 exec 5<> /dev/tcp/outian.net/80
表示將連線 outian.net:80 , 並開啟在 fd 5 (只要不衝到 任何 fd 都可)
( bash manpage 中對 <> 的說明是
『 Opening File Descriptors for Reading and Writing 』 )
然後 printf "GET / HTTP/1.0\n\n" >& 5
則是把 GET / HTTP/1.0
這串 HTTP Request 送到 fd 5 , 也就是傳往 socket 另一端
接著 cat <& 5
表示從 fd 5 讀出資料 , 就會看到傳回來的 HTTP content
最後 exec 5<&-
表示 close fd 5
應用2 - 去掉 HTTP Response Header , 只保留後面的 content
( 這樣在一些場合下, 沒有 wget/fetch/lynx , 又需要拿外面的檔案時就很好用了 ~ )
例如將這樣一段 script 存成 wget.sh
#!/bin/sh
TEMP=/tmp/$$.tmp
HOST=`echo $1 | cut -d/ -f3`
PATHFILE=/`echo $1 | cut -d/ -f4-`
{
exec 5<> /dev/tcp/$HOST/80
printf "GET $PATHFILE HTTP/1.0\nHOST: $HOST\n\n" >&5
cat <&5
exec 5>&-
} > $TEMP
L=`head $TEMP | col -b | awk ‘/Content-Length:/ {print $NF}'`
if [ -z $L ] ; then
echo file not found
else
tail -c$L $TEMP > `basename $1`
echo `basename $1` saved
fi
rm $TEMP
稍微說明一下,
首先抓出後面網址中的 host 、 file
然後用 bash 的 socket communication 功能連線取得完整 HTTP Message
存到 /tmp/$$.tmp ( $$ 為該 process 的 pid )
但是若只要檔案的部份, 還必需去掉 HTTP Response Header
其中一種方法是檢查 Header 中的 Content-Length,然後從存下的檔案末端截取該長度
即是完整的 HTTP Content ...
ex: sh wget.sh http://outian.net/temp/tuu.png
另一種作法, 可以 \r\n\r\n 為 seperator 將 HTTP Message 切成兩部份
第一部份是 HTTP Response Header , 第二部份即為 HTTP Content ..
ex :
printf "GET /temp/tuu.png HTTP/1.0\n\n" | nc outian.net 80 | \
perl -e ‘print ((split("\r\n\r\n",join("",<>),2))[1]);' > tuu.png
這樣也可以抓回檔案.
vim
.Linux 類別的文章 :
Auto Login console in Linux
.Shell 類別的文章 :
5 則留言 新增留言
1. 傑洛 | February 8th, 2007 at 09:45
剛剛測試了一下,Mac OSX的bash也有支援。
2. openblue | February 9th, 2007 at 10:39
我通常直接在web中
http://www.cmyip.com/
這裡就可看到了
3. OuTian | February 9th, 2007 at 17:12
http://www.cmyip.com/ 太多東西啦
command line 拿下來一堆
所以我都用自家牌的 :p
4. LORD | February 12th, 2007 at 12:22
都可以連上網路了
所以我都用不會寫程式的人的懶方法
pcman–>工具–>取得本機ip位址
XD
5. Oldcat | February 12th, 2007 at 16:04
我來亂入一下
因為上班不能開bbs,太明顯了
只好找這篇來亂入
剛剛無意間看到這個站
http://gaaan.com/
這玩意看起來很有趣,你要不要改寫你的傳說看看lol
新增留言
訂閱這則留言的 RSS Feed