概要
Echo server というのはサーバー界のhello world
だと言っても過言でもありません。サーバーサイドの入門に一番相応しい練習です。
実現する機能は、クライエントから送信された文字を返信するのです。
今回は、それ以外の機能は一切入れないプログラムを作りましょう!
プログラムの流れ
サーバーサイド
サーバ起動
->サーバー側のソケットを作る
-> クライエントからの接続リクエストを待つ
-> 接続を許可する
-> 受信待ち&処理ループ
-> クライエントからの停止シグナル(空データ)
-> ソケットを閉じる
-
socket
を作成する
pythonでは、オフィシャルライブラリーsocket
を提供していますので。そのままimport
すれば使えるようになります。
AF_INET
の由来はlinuxのsocket callのパラメータです。ipv4を指定する。
また、SOCK_STREAM
はTCPを代表する。import socket server_socket = (socket.AF_INET,socket.SOCK_STREAM)
これで新しいソケットを作成しました。
-
bind()
サーバーのsocketをサインする
socket
を利用するには、必ずportとipアドレスを指定する。
サーバーの場合ipアドレスは必ず自身のipを指定すること。server_socket.bind(("127.0.0.1",12345))
明らかに、複数のsocketを一つのportにバインディングしていけない
-
listen()
遠方アドレスの行列を作る
listen
のところに入らった、クライント側から受信するまで、プログラムはここでブロックされます。server_socket.listen(1)
listen()
の引数はbacklog
の数を指定するのです。backlog
は
待てるクライエントのsocket
の数を指定します。0
に設定すると、一番最初に来たクライエントsocketをキューに押したら、後に来てくるすべてのsocketを拒みます。 -
accept
Finally,I accepted you.
listen()
はただ「socketが来た」との情報をサーバーサイドに知らせるだけです。その後accpet()
でキューからsocketを取り、接続します。accept()
は2つの戻り値値を返しています。-
sock
: socket オブジェクト -
addr
: Turpleオブジェクト。接続先のsocketにバインディングしているアドレス
client_socket,client_address = server_socket.accept()
これで接続ができました
-
-
受信処理
基本的にはWhile True
を使って無限ループで処理します-
recv()
bufferを設置
socketでデータを伝送するには、送信でも受信でもbufferサイズを指定する必要があります。pythonでは、データを受信する同時にbufferサイズを設置します。
data = client_socket.recv(1024)
受信したデータをサーバのコンソールに示したい場合は、
data
をdecodeする必要があります。str_data = data.decode() print("Received from client",str_data)
-
send()
受信が成功でしたら、すぐ処理できるようになります。今回作りたいのはechoサーバーなので、受信したデータを直接返信すれば良いです。
TCPで通信する場合はsend()
を使います。ちなみに一方UDPの場合はsendto()
という関数があります。
client_socket.send(data)
-
close()
送信側からサービス停止シグナル(ここは空データを約束したif not data : break
)を受けたら、クライエントのソケットを閉じる。サーバーサイドのソケットは次の接続を処理することができるようになりました。
client_socket.close()
-
クライエント
クライエント起動
-> ソケットを作成
-> サーバーに接続
-> ユーザー入力処理/発送/受け取る
-> ユーザーが空データを入力したらクライエントを停止する
1.socket
を作成する
サーバー側と同じです。
client_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
2.connect()
サーバーに接続します
client_socket.connect(("127.0.0.1",45621))
3.send()
送信
ネットワークにデータを送信する時に、必ず encodeすること。
client_socket.send(data.encode())
4.recv
受信
client_socket.recv(1024)
5.close()
クライエント側のsocketを閉じる
client_socket.close()
全体コード
#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()
#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()
次回
複数のユーザーに対する処理