【備忘録】PythonでTCP and UDP Socketを作ってみた。

#はじめに
セキュリテイに関する本を友人からカリパクしていたので、その備忘録として記事にしてみます。

#本記事の概要
Pythonでサーバ/クライアント通信を行うサードパーティー製のツールはたくさんあるが、その核となっているのがSocketライブラリらしい。なので、このライブラリを使用してみる。

#環境
- OS : ManjaroLinux
- Vitualenv : Python2.7

#TCP Client
単純なTCPクライアント

```python:tcp_client.py
#-*- coding: utf-8 -*-
import socket

target_host = "www.google.com"
target_port = 80

#オブジェクトの生成
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

#接続
client.connect((target_host,target_port))
#データの送信
client.send("GET / HTTP/1.1\r\nHOST: google.com\r\n\r\n")
#データの受信
response = client.recv(4096)

print response
```

実行してみる。

```console
$ python tcp_client.py
HTTP/1.1 301 Moved Permanently
Location: http://www.google.com/
Content-Type: text/html; charset=UTF-8
Date: Sun, 20 May 2018 11:36:57 GMT
Expires: Tue, 19 Jun 2018 11:36:57 GMT
Cache-Control: public, max-age=2592000
Server: gws
Content-Length: 219
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN

<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="http://www.google.com/">here</A>.
</BODY></HTML>
```
301のステータスコード（永続的なリダイレクト）
まぁ、気にせずにいこうかと。
ちなみ、レスポンスで返ってきているServerヘッダーのgwsが見慣れないので軽く調べたら
グーグル・ウェブサーバ (Google Web Server, 略称 GWS)の略らしい。

#UDP Client
単純なUDPクライアント

```python:udp_client.py
# -*- encoding: utf-8 -*-

import socket

target_host = "127.0.0.1"
target_port = 80

# socketオブジェクトの作成
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# データの送信
client.sendto("hogehoe",(target_host,target_port))

# データの受信
data, addr = client.recvfrom(4096)

print data
```
さてと、どうやって確認しましょうか。
よーし、みんな大好きtcpdumpでいきましょう。

```console
$ sudo tcpdump -i lo
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
20:57:24.678400 IP localhost.57138 > localhost.http: UDP, length 7
20:57:24.678422 IP localhost > localhost: ICMP localhost udp port http unreachable, length 43
```
まぁ、なにかが飛んできているのはわかった。length 7ってのは"hogehoe"の文字数なのかな？
とりあえず、先に進みます。

#TCP Server
単純なTCP Server

```python:tcp_server.py
# -*- encoding: utf-8 -*-

import socket
import threading

bind_ip = "0.0.0.0"
bind_port = 9999

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

server.bind((bind_ip, bind_port))

server.listen(5)

print "[*] Listening on %s:%d" % (bind_ip, bind_port)

# クライアントからの接続を処理するスレッド
def handle_client(client_socket):

    # クライアントが送信してきたデータを表示
    request = client_socket.recv(1024)

    print "[*] Received: %s" % request

    # パケットの返送
    client_socket.send("ACK!")
    client_socket.close()

while True:

    client,addr = server.accept()

    print "[*] Accepted connection from: %s:%d" % (addr[0],addr[1])

    # 受信データを処理するスレッドの起動
    client_handler = threading.Thread(target=handle_client,args=(client,))
    client_handler.start()
```

実行してみます。

```console
$ python tcp_server.py 
[*] Listening on 0.0.0.0:9999
[*] Accepted connection from: 127.0.0.1:44198
[*] Received: ABCDEF
```

クライアントはこういう感じです。

```console
$ python tcp_socket.py 
ACK!

$ cat tcp_socket.py 
# -*- encoding: utf-8 -*-

import socket

target_host = "localhost"
target_port = 9999

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

client.connect((target_host,target_port))

client.send("ABCDEF")

response = client.recv(4096)

print response
```
今回は以上になります。