前回の記事と一緒にご覧ください。Python3のソケットモジュールとソケット通信の流れ
python3のsocketモジュールを使った、TCP通信の簡単な例
#####環境
Python: 3.6
必要とするモジュール: colorama
実行結果とソースコード
サーバー側(ソケット通信二回分)
import socket
from colored_print import print_msg
SERVER_ADDRESS = ('192.168.1.200', 8000)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(SERVER_ADDRESS)
sock.listen(0)
for i in range(2):
try:
conn_sock, client_address = sock.accept()
print_msg('ac', 'The connection accepted.')
print_msg('i', '{}:{} --------> {}:{}'
.format(client_address[0], client_address[1],
SERVER_ADDRESS[0], SERVER_ADDRESS[1]))
# Receiving process
amount_received = 0
MSGLEN = int(conn_sock.recv(4))
print_msg('i', 'MSGLEN: {}'.format(MSGLEN))
while amount_received < MSGLEN:
data = conn_sock.recv(min(MSGLEN - amount_received, 32))
print_msg('i', 'received: {}'.format(data))
amount_received += len(data)
if not data:
raise RuntimeError('The connected socket broken.')
# Sending process
conn_sock.send(data)
print_msg('i', 'send: {}'.format(data))
finally:
conn_sock.close()
print_msg('cl', 'The connection closed.')
クライアント側
import socket
from colored_print import print_msg
SERVER_ADDRESS = ('192.168.1.200', 8000)
MSG = 'Alice was beginning to get very tired of sitting by her sister on the bank, and of having nothing to do.'
MSGLEN = len(MSG)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.connect(SERVER_ADDRESS)
print_msg('cn', 'The connection accepted')
print_msg('i', 'MSGLEN: {}'.format(MSGLEN))
sock.send(bytes(str(MSGLEN), 'utf-8').zfill(4))
# Sending process
sock.send(bytes(MSG, 'utf-8'))
# Receiving process
chunks = []
amount_received = 0
while amount_received < MSGLEN:
data = sock.recv(min(MSGLEN - amount_received, 32))
print_msg('i', 'received: {}'.format(data))
amount_received += len(data)
if not data:
raise RuntimeError('The connected socket broken.')
chunks.append(data)
finally:
sock.close()
print_msg('cl', 'The connection closed.')
result = '''
Result: [
MSGLEN: {},
Send: {},
Received: {}
]
'''.format(MSGLEN, MSG, chunks)
print_msg('i', result)
解説
recvのループのブレイクは、
-
b''
が来たらブレイクする。 - メッセージの長さがわかるなら受信分の長さがメッセージの長さと等しくなったらブレイクする。
のに種類があるが、1.の問題点は通信の途中で通信が壊れたときにもb''
が渡されるということ。そこで今回は新しくはじめに送る4バイトはメッセージの長さであると言うルールを作った。
サーバー側
[ACCEPT]
から[CLOSE]
までが一つのソケット通信。
クライアントから来たメッセージを受け取ったらすぐに送り返す。
クライアント側
[CONNECT]
から[CLOSE]
までが一つのソケット通信。
##colored_print
下のコードを同じディレクトリに配置してください。
colored_print.py
from colorama import Fore, Style
def print_msg(header, msg):
'''header are i that is INFO or e that is ERROR'''
if header == 'i':
print(Fore.GREEN + '[INFO]',
Style.RESET_ALL + msg)
elif header == 'e':
print(Fore.RED + '[ERROR]',
Style.RESET_ALL + msg)
elif header == 'ac':
print(Fore.BLUE + '[ACCEPT]',
Style.RESET_ALL + msg)
elif header == 'cn':
print(Fore.BLUE + '[CONNECT]',
Style.RESET_ALL + msg)
elif header == 'cl':
print(Fore.BLUE + '[CLOSE]',
Style.RESET_ALL + msg)
else:
print(Fore.RED + 'ERROR: header is an invalid value.'
+ Style.RESET_ALL)