pythonで簡単な echo サーバーを作りましょう

# 概要

Echo server というのはサーバー界の`hello world`だと言っても過言でもありません。サーバーサイドの入門に一番相応しい練習です。
実現する機能は、クライエントから送信された文字を返信するのです。
今回は、それ以外の機能は一切入れないプログラムを作りましょう！

# プログラムの流れ

## サーバーサイド  
  
  サーバ起動  
  ->サーバー側のソケットを作る  
  -> クライエントからの接続リクエストを待つ  
  -> 接続を許可する  
  -> 受信待ち&処理ループ  
  -> クライエントからの停止シグナル（空データ）  
  -> ソケットを閉じる  

1. `socket`を作成する 
    pythonでは、オフィシャルライブラリー`socket`を提供していますので。そのまま`import`すれば使えるようになります。
    `AF_INET`の由来はlinuxのsocket callのパラメータです。ipv4を指定する。
    また、`SOCK_STREAM`はTCPを代表する。
    
    ```python
    import socket
    server_socket = (socket.AF_INET,socket.SOCK_STREAM)
    ``` 
    これで新しいソケットを作成しました。  

2. `bind()`  サーバーのsocketをサインする
    `socket`を利用するには、必ずportとipアドレスを指定する。  
    サーバーの場合**ipアドレスは必ず自身のipを指定すること。**

    ```python
    server_socket.bind(("127.0.0.1",12345))
    ```

    **明らかに、複数のsocketを一つのportにバインディングしていけない**

3. `listen()` 遠方アドレスの行列を作る
    `listen`のところに入らった、クライント側から受信するまで、プログラムはここでブロックされます。

    ```python
    server_socket.listen(1)
    ```

    `listen()`の引数は`backlog`の数を指定するのです。`backlog`は  
    待てるクライエントの`socket`の数を指定します。`0`に設定すると、一番最初に来たクライエントsocketをキューに押したら、後に来てくるすべてのsocketを拒みます。
    
4. `accept` Finally,I accepted you.  
    `listen()`はただ「socketが来た」との情報をサーバーサイドに知らせるだけです。その後`accpet()`でキューからsocketを取り、接続します。

    `accept()`は2つの戻り値値を返しています。  
    * `sock`: socket オブジェクト  
    * `addr`: Turpleオブジェクト。接続先のsocketにバインディングしているアドレス

    ```python
    client_socket,client_address = server_socket.accept()
    ```

    これで接続ができました

5. `受信処理`  
    基本的には`While True`を使って無限ループで処理します  
    * `recv()` bufferを設置  
    socketでデータを伝送するには、送信でも受信でもbufferサイズを指定する必要があります。pythonでは、データを受信する同時にbufferサイズを設置します。
    
    ```python
    data = client_socket.recv(1024)
    ```

    受信したデータをサーバのコンソールに示したい場合は、`data`をdecodeする必要があります。

    ```python
    str_data = data.decode()
    print("Received from client",str_data)
    ```
    
   * `send()`
    受信が成功でしたら、すぐ処理できるようになります。今回作りたいのはechoサーバーなので、受信したデータを直接返信すれば良いです。
    TCPで通信する場合は`send()`を使います。ちなみに一方UDPの場合は`sendto()`という関数があります。  

    ```python
    client_socket.send(data)
    ```

    * `close()`
    送信側からサービス停止シグナル（ここは空データを約束した`if not data : break`）を受けたら、クライエントのソケットを閉じる。サーバーサイドのソケットは次の接続を処理することができるようになりました。

    ```python
    client_socket.close()
    ```
    
## クライエント
  
  クライエント起動
  -> ソケットを作成
  -> サーバーに接続
  -> ユーザー入力処理/発送/受け取る
  -> ユーザーが空データを入力したらクライエントを停止する

1.`socket`を作成する  
サーバー側と同じです。  

```python
client_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
```

2.`connect()` サーバーに接続します  

```python
client_socket.connect(("127.0.0.1",45621))
```

3.`send()` 送信  

ネットワークにデータを送信する時に、必ず encodeすること。

```python
client_socket.send(data.encode())
```

4.`recv`受信  

```python
client_socket.recv(1024)
```

5.`close()` クライエント側のsocketを閉じる

```python
client_socket.close()
```



全体コード

```python
#server
from os import terminal_size
import socket
server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server_socket.bind(("127.0.0.1",45621))
server_socket.listen(1)
client_socket,client_address = server_socket.accept()
print("Connection from",client_address)
while True:
  data = client_socket.recv(1024)
  str_data = data.decode()
  if not data : break
  print("Received from client",str_data)
  client_socket.send(data)
#client_address.close()
client_socket.close()
```

```python
#client
import socket

client_socket = socket.socket()
client_socket.connect(("127.0.0.1",45621))
while True:
  data = input(">")
  client_socket.send(data.encode())
  if  not data:break
  newData = client_socket.recv(1024)
  print("Received from server:" ,str(newData.decode()))
client_socket.close()
```

# 次回
複数のユーザーに対する処理