LoginSignup
7
5

More than 1 year has passed since last update.

TCP通信 python整理

Last updated at Posted at 2023-03-08

はじめに

TCPを利用したソケット通信について、整理しておきます。

基礎用語

1. クライアントソケットの利用手順

  1. ソケットの作成 : socket()
  2. ソケットの設定とサーバーへの接続: connect()
  3. データのやり取り: send(), recv()
  4. コネクションをクローズする: close()

2. サーバーソケットの利用手順

  1. ソケットの作成 : socket()
  2. アドレスとポート番号の設定: bind()
  3. 接続の待ち受け: listen()
  4. 通信用ソケットの取得:accept()
  5. データのやり取り: send(), recv()
  6. コネクションをクローズする: 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. クライアント側のソケット実装

基本的なクライアントプログラムを実装します。

  1. ネットワーク層:IPv4
  2. トランスポート層: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.一回だけクライアントからの接続を受け付けてすぐに終了するサーバープログラム

  1. ネットワーク層:IPv4
  2. トランスポート層:TCP

実装手順

  1. ソケットの作成 : socket()
  2. アドレスとポート番号の設定: bind()
  3. 接続の待ち受け: listen()
  4. 通信用ソケットの取得:accept()
  5. データのやり取り: send(), recv()
  6. コネクションをクローズする: 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.繰り返して接続を受け付けてサーバープログラム

  1. ネットワーク層:IPv4
  2. トランスポート層:TCP

実装手順

  1. ソケットの作成 : socket()
  2. アドレスとポート番号の設定: bind()
  3. 接続の待ち受け: listen()
  4. while True
    1. 通信用ソケットの取得:accept()
    2. データのやり取り: send(), recv()
    3. コネクションをクローズする: 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()

追加勉強資料

  1. threadingより非同期処理の場合、こちらが参考になります。
    https://qiita.com/sand/items/4f27e62c7491b8e85d12
7
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
5