ネットワークのお勉強してみた

やること

  1. telnet をつかって http リクエストを発行する
  2. python で socket 関数を利用して http クライアントを実装する
  3. python で socket 関数を利用して http サーバを実装する

1. telnet してみる

  • なにはともあれやってみる
    • 対象はヤフーのトップページ
$ telnet www.yahoo.co.jp 80
Trying 203.216.247.249...
Connected to www.ya.gl.yahoo.co.jp.
Escape character is '^]'.
GET /index.html HTTP/1.0

HTTP/1.1 200 OK
Date: Wed, 14 Apr 2010 16:25:50 GMT
P3P: policyref="http://privacy.yahoo.co.jp/w3c/p3p.xml", CP="CAO DSP COR CUR ADM DEV TAI PSA PSD IVAi IVDi CONi TELo OTPi OUR DELi SAMi OTRi UNRi PUBi IND PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE GOV"
Cache-Control: no-cache
Cache-Control: no-store, must-revalidate
Expires: -1
Pragma: no-cache
X-XRDS-Location: http://open.login.yahoo.co.jp/openid20/www.yahoo.co.jp/xrds
Cache-Control: private
Connection: close
Content-Type: text/html; charset=utf-8

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
 - 省略 -
</html>
Connection closed by foreign host.
  • 通信の流れ
  1. telnet で 80番ポートに接続する
  2. サーバに送信するリクエストを入力する
  3. リターンキーを2回押してリクエストを送信する
  4. レスポンスを受け取る
  5. 接続が切断される


2. http client を作ってみる

  • http_client.py
  1 import socket
  2 
  3 host = socket.gethostbyname('www.yahoo.co.jp')
  4 port = 80
  5 
  6 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  7 sock.connect((host, port))
  8 sock.send("GET /index.html HTTP/1.0 \n\n")
  9 
 10 msg = sock.recv(1024)
 11 sock.close()
 12 
 13 print msg
 14 
  • 実行する
$ python http_client.py 
HTTP/1.1 200 OK
Date: Wed, 14 Apr 2010 16:47:06 GMT
P3P: policyref="http://privacy.yahoo.co.jp/w3c/p3p.xml", CP="CAO DSP COR CUR ADM DEV TAI PSA PSD IVAi IVDi CONi TELo OTPi OUR DELi SAMi OTRi UNRi PUBi IND PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE GOV"
Cache-Control: no-cache
Cache-Control: no-store, must-revalidate
Expires: -1
Pragma: no-cache
X-XRDS-Location: http://open.login.yahoo.co.jp/openid20/www.yahoo.co.jp/xrds
Cache-Control: private
Connection: close
Content-Type: text/html; charset=utf-8

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta http-equiv="content-style-type" content="text/css">
<meta http-equiv="content-script-type" content="text/javascript">
<meta name="description" content="日本最大級のポータルサイト。検索、オークション、ニュース、メール、コミュニティ、ショッピング、など80
  • プログラムの流れ
  1. socket を生成する
  2. 指定した host, port に接続する
  3. 接続先にメッセージを送る
  4. 接続先からのメッセージを受け取る
  5. socket を閉じる

3. http server を作ってみる

  • ソース
  1 import socket
  2 
  3 host = socket.gethostbyname('localhost')
  4 port = 8080
  5 
  6 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  7 sock.bind((host, port))
  8 sock.listen(1)
  9 
 10 print 'waiting for connection...'
 11 
 12 (client_sock, client_addr) = sock.accept()
 13 
 14 client_sock.send("server : connection start \n\n")
 15 print 'connection start'
 16 
 17 while True:
 18   msg = client_sock.recv(1024)
 19   msg = msg.rstrip()
 20 
 21   if msg == "":
 22     client_sock.send("server : connection end \n\n")
 23     print 'connection end'
 24     break
 25 
 26   else:
 27     print "client : %s" % msg
 28 
 29 client_sock.close()
 30 
 31 sock.close()
 32 
  • 実行して telnet で確認する

server 側

$ python http_server.py 
waiting for connection...
connection start
client : this
client : is
client : server
client : test
connection end

client 側

$ telnet localhost 8080
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
server : connection start 

this
is
server
test

server : connection end 

Connection closed by foreign host.
  • プログラムの流れ
  1. socket を生成する
  2. bind で待ち受ける host, port を指定する
  3. listen で待ち受けを開始する
  4. accept で接続待ちをする
  5. recv で クライアントから送られてくるメッセージを受け取る
  6. メッセージが空でなければ出力、空の場合はループを抜けてクライアントとの接続を切る
  7. socket を閉じる

まとめ

  • telnet で http リクエストを送ることができた
    • 今回はリクエストに GET~ しか記述していないが、他にも Referer, User-Agent などが指定できる
      • この辺りは http の仕様の勉強が必要である
  • エラー処理などはしていないが、簡単な http クライアントとサーバが作れた
  • socket 関数を使って開発したことで、通信のやりとりが何となくわかったと思う

参考