はじめに
TCPを利用したソケット通信について、整理しておきます。
基礎用語
1. クライアントソケットの利用手順
- ソケットの作成 :
socket()
- ソケットの設定とサーバーへの接続:
connect()
- データのやり取り:
send()
,recv()
- コネクションをクローズする:
close()
2. サーバーソケットの利用手順
- ソケットの作成 :
socket()
- アドレスとポート番号の設定:
bind()
- 接続の待ち受け:
listen()
- 通信用ソケットの取得:
accept()
- データのやり取り:
send()
,recv()
- コネクションをクローズする:
close()
#Pythonでの利用
1. ホスト名からIPアドレス取得プログラム
socketモジュール
socket.gethostbyname()を利用
import socket
hostname = 'www.qiita.com'
IP_address = socket.gethostbyname(hostname)
print(f'IP address of {hostname} is {IP_address}')
Result
IP address of www.qiita.com is 54.249.74.29
Process finished with exit code 0
2. クライアント側のソケット実装
基本的なクライアントプログラムを実装します。
- ネットワーク層:IPv4
- トランスポート層:TCP
5000番ポートでサーバーに接続します。
使い方:python client_socket_IP4.py
client_socket_IP4.py
'''
This program shows the way how to use
socket client in python.
'''
#Process
#01. Preparing Socket : socket()
#02. Configuring Soccket and Connect to the Server : connect()
#03. Data Yaritori : send(), recv()
#04. Closing the connection : close()
import socket
HOST = '192.168.0.164'
PORT = 5000
BUFSIZE = 4096
#01. Preparing Socket : socket()
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#socket.AF_INET : IPv4
#socket.SOCK_STREAM : TCP
#02. Configuring Soccket and Connect to the Server : connect()
client.connect((HOST,PORT))
#03. Data Yaritori : send(), recv()
data = client.recv(BUFSIZE)
print(data.decode('UTF-8'))
#04. Closing the connection : close()
client.close()
3. サーバー側のソケット実装
3.1.一回だけクライアントからの接続を受け付けてすぐに終了するサーバープログラム
- ネットワーク層:IPv4
- トランスポート層:TCP
実装手順
- ソケットの作成 :
socket()
- アドレスとポート番号の設定:
bind()
- 接続の待ち受け:
listen()
- 通信用ソケットの取得:
accept()
- データのやり取り:
send()
,recv()
- コネクションをクローズする:
close()
server_single_connection.py
'''
This program shows the way how to make your pc
into server with socket in python.
'''
#-----------------------------------------------
#Process
#01. Socket Making : socket()
#02. Address & Port : bind()
#03. Waiting the connection : listen()
#04. Getting the socket : accept()
#05. Data Yaritori : send(), recv()
#06. Closing the connection()
#-----------------------------------------------
import socket
#Port Number
PORT = 5000
#Main
#01. Socket Making : socket()
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#02. Address & Port : bind()
server.bind(("", PORT))
#03. Waiting the connection : listen()
server.listen()
#04. Getting the socket : accept()
client, addr = server.accept()
#05. Data Yaritori : send(), recv()
client.sendall(b"Hi, nice to meet you!\n") #messeage
#06. Closing the connection()
client.close()
server.close()
3.2.繰り返して接続を受け付けてサーバープログラム
- ネットワーク層:IPv4
- トランスポート層:TCP
実装手順
- ソケットの作成 :
socket()
- アドレスとポート番号の設定:
bind()
- 接続の待ち受け:
listen()
- while True
- 通信用ソケットの取得:
accept()
- データのやり取り:
send()
,recv()
- コネクションをクローズする:
close()
- 通信用ソケットの取得:
server_continous_connection.py
'''
This program shows the way how to make your pc
into server with socket in python.
Ctrl + Break : quit
'''
#-----------------------------------------------
#Process
#01. Socket Making : socket()
#02. Address & Port : bind()
#03. Waiting the connection : listen()
#04. Getting the socket : accept()
#05. Data Yaritori : send(), recv()
#06. Closing the connection()
#-----------------------------------------------
import datetime
import socket
PORT = 5000
SERVER = socket.gethostbyname(socket.gethostname())
ADDR = (SERVER, PORT)
FORMAT = 'utf-8'
#01. Socket Making : socket()
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#02. Address & Port : bind()
# server.bind(("", PORT))
server.bind(ADDR)
#03. Waiting the connection : listen()
server.listen()
try:
while True :
print(f'[NEW Connection] {ADDR} connected.')
# 04. Getting the socket : accept()
client, addr = server.accept()
# 05. Data Yaritori : send(), recv()
msg = str(datetime.datetime.now())
client.sendall(msg.encode("UTF-8"))
print(f'{msg} : 接続要求あり')
print(client)
client.close()
except KeyboardInterrupt:
print('Finished!')
4. クライアントとサーバーが双方向の通信を行う。
4.1. 双方向の通信を行うクライアントプログラム
client_souhoukou.py
'''
This program shows the way how to use
socket client in python.
'''
#Process
#01. Preparing Socket : socket()
#02. Configuring Soccket and Connect to the Server : connect()
#03. Data Yaritori : send(), recv()
#04. Closing the connection : close()
import socket
HOST = '192.168.0.195'
PORT = 5000
BUFSIZE = 4096
FORMAT = 'utf-8'
#01. Preparing Socket : socket()
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#02. Configuring Soccket and Connect to the Server : connect()
client.connect((HOST,PORT))
#03. Data Yaritori : send(), recv()
# サーバーへのメッセージ
msg = input('Input the msg to server:')
client.sendall(msg.encode(FORMAT))
# サーバーからのメッセージを受信
data = client.recv(BUFSIZE)
print('サーバーからのメッセージ')
print(data.decode(FORMAT))
#04. Closing the connection : close()
client.close()
4.2. 双方向の通信を行うクライアントプログラム
server_continous_souhoukou.py
'''
This program shows the way how to make your pc
into server with socket in python.
Ctrl + Break : quit
'''
#-----------------------------------------------
#Process
#01. Socket Making : socket()
#02. Address & Port : bind()
#03. Waiting the connection : listen()
#04. Getting the socket : accept()
#05. Data Yaritori : send(), recv()
#06. Closing the connection()
#-----------------------------------------------
import datetime
import socket
PORT = 5000
BUFSIZE = 4096
SERVER = socket.gethostbyname(socket.gethostname())
ADDR = (SERVER, PORT)
FORMAT = 'utf-8'
#01. Socket Making : socket()
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#02. Address & Port : bind()
server.bind(ADDR)
#03. Waiting the connection : listen()
server.listen()
#
try:
while True :
print(f'[NEW Connection] {ADDR} connected.')
# 04. Getting the socket : accept()
client, addr = server.accept()
# 05. Data Yaritori : send(), recv()
# 確認
msg = str(datetime.datetime.now())
print(f'{msg} : 接続要求あり')
print(client)
#クライアントより受信
data = client.recv(BUFSIZE)
print(data.decode(FORMAT))
#サーバーから送信
client.sendall(msg.encode(FORMAT))
# 06. Closing the connection()
client.close()
except KeyboardInterrupt:
print('Finished!')
4. サーバーの処理をマルチスレッド化する。
4.1. クライアント側プログラム
client_code.py
import socket
HEADER = 64
PORT = 5050
FORMAT = 'utf-8'
DISCONNECT_MESSAGE = "!DISCONNECT"
SERVER = "192.168.0.195"
ADDR = (SERVER, PORT)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(ADDR)
def send(msg):
message = msg.encode(FORMAT)
msg_length = len(message)
send_length = str(msg_length).encode(FORMAT)
send_length += b' ' * (HEADER - len(send_length))
client.send(send_length)
client.send(message)
print(client.recv(2048).decode(FORMAT))
send("Hello World!")
input()
send("Hello Everyone!")
input()
send("Hello Tim!")
send(DISCONNECT_MESSAGE)
4.2. マルチスレッド化されたサーバー側プログラム
server_code.py
import socket
import threading
HEADER = 64
PORT = 5050
SERVER = socket.gethostbyname(socket.gethostname())
ADDR = (SERVER, PORT)
FORMAT = 'utf-8'
DISCONNECT_MESSAGE = "!DISCONNECT"
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(ADDR)
def handle_client(conn, addr):
print(f"[NEW CONNECTION] {addr} connected.")
connected = True
while connected:
msg_length = conn.recv(HEADER).decode(FORMAT)
if msg_length:
msg_length = int(msg_length)
msg = conn.recv(msg_length).decode(FORMAT)
if msg == DISCONNECT_MESSAGE:
connected = False
print(f"[{addr}] {msg}")
conn.send("Msg received".encode(FORMAT))
conn.close()
def start():
server.listen()
print(f"[LISTENING] Server is listening on {SERVER}")
while True:
conn, addr = server.accept()
thread = threading.Thread(target=handle_client, args=(conn, addr))
thread.start()
print(f"[ACTIVE CONNECTIONS] {threading.activeCount() - 1}")
print("[STARTING] server is starting...")
start()
追加勉強資料
- threadingより非同期処理の場合、こちらが参考になります。
https://qiita.com/sand/items/4f27e62c7491b8e85d12