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

這樣也可以抓回檔案.


Programming 類別的文章 :
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


各分類文章

最近的 20 篇文章