Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

Socketモジュールを使ったTCP通信 - Python3

前回の記事と一緒にご覧ください。Python3のソケットモジュールとソケット通信の流れ
python3のsocketモジュールを使った、TCP通信の簡単な例

環境

Python: 3.6
必要とするモジュール: colorama

実行結果とソースコード

サーバー側(ソケット通信二回分)

server_side_img.jpg

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.')

クライアント側

client_side_img.jpg

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のループのブレイクは、

  1. b''が来たらブレイクする。
  2. メッセージの長さがわかるなら受信分の長さがメッセージの長さと等しくなったらブレイクする。

のに種類があるが、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)
Suzukaze31
初投稿です。どうぞお手柔らかに。 間違っているところなどあれば指摘してもらえると感謝します。 大体コマンドではEnterが省略されています。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away