【ソケット通信】Pythonでシンプルなソケット通信を実現 | サーバーとクライアント

ヒント: 記事を作成した後、目次を自動的に生成できます。生成方法は、右側のヘルプドキュメントを参照してください。


序文

参考内容:
1) TCP/IPネットワーク通信のソケットプログラミング入門

1. ソケット通信の基礎知識

1.1 基礎知識

ソケットはソケットとも呼ばれます。
ソケットの起動に必要な基本情報:通信用のホスト番号ポート番号(ポート番号は実際にはプロセス、つまりホスト上のどのアプリケーション プログラムが通信するかを表します)
ソケットは 2 台のコンピュータ間をデータ線のように接続し、通信ブリッジとして機能します。

1.2ソケットタイプ

ソケットには通常、TCP と UDP の2 つのタイプがあります。
TCP: Transmission Control Protocol 伝送制御プロトコル
TCP プロトコルは信頼性が高く、送信されたデータは相手に受信されます。TCP はデータストリームベースのプロトコル (データストリーム)
UDP: User Datagram Protocol ユーザー データグラム プロトコル
UDP は信頼性が低く、必ずしもデータが相手に受信されることを保証するものではありません。UDP は一般に遅延が短く、使用するリソースも少なくなります (音声通話に適しています)。

次の内容は、chatGPTによってキャプチャされた TCP および UDP のナレッジ ポイントに基づいています。

TCP と UDP は 2 つの異なるネットワーク トランスポート プロトコルです。TCP (Transmission Control Protocol) は、信頼性の高い接続を確立し、その接続上でデータを送信する接続指向のプロトコルです。UDP (User Datagram Protocol) は、データの信頼性の高い送信を保証しないコネクションレス型プロトコルです。TCPプロトコルはデータ送信前に3ウェイハンドシェイクを必要とするため、接続確立後のデータ送信の信頼性は高いものの、送信効率は低くなります。UDPプロトコルはコネクションを確立する必要がなく、伝送効率は高いですが、データの信頼性は保証できません。
TCP プロトコルは、電子メール、ファイル転送、Web ブラウジングなど、信頼性の高いデータ送信が必要なシナリオに適しています。UDP プロトコルは、オーディオやビデオのストリーミングなど、高速伝送が必要なシナリオに適しています。

2、ソケットPythonの実装

2.1. サーバーコードserver.py

import socket

# 创建socket对象
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 获取本地主机名和端口号
host = socket.gethostname()
port = 8888

# 将socket对象绑定到指定的主机和端口上
server_socket.bind((host, port))

# 开始监听连接
server_socket.listen(1)

# 等待客户端连接
print("等待客户端连接...")
client_socket, client_address = server_socket.accept()

print("连接来自: ", client_address)

# 接收客户端发送的数据
data = client_socket.recv(1024)

# 处理接收到的数据
print("接收到的数据为: ", data.decode())

# 发送响应数据给客户端
message = "欢迎连接到服务器!"
client_socket.send(message.encode())

# 关闭客户端连接
client_socket.close()

1)ソケット.gethostname()とsocket.gethostbyname()は異なります。socket.gethostname
()は、ソケット接続で使用する現在のホストのホスト名を取得します。ソケット接続にホスト名の代わりに IP アドレスを使用する場合は、socket.gethostbyname() 関数を使用してホストの IP アドレスを取得できます。
2) ポート番号について
socket.bind()メソッドでソケットオブジェクトにIPアドレスとポート番号をバインドすると、ソケットオブジェクトには一意のポート番号が割り当てられます。このポート番号を利用してデータを送受信し、Socket通信を実現します。
クライアントがこのサーバーに接続する場合、クライアントはサーバーの IP アドレスとポート番号を知っている必要があります。クライアントはこのポート番号を介して Socket 接続を確立し、サーバーと通信してデータの送信と交換を実現します。したがって、ポート番号はソケット通信において非常に重要な概念です。
このポート番号はこのソケット オブジェクト用です。
3) server_socket.accept()
server_socket.accept() は、クライアントが接続するまでプログラムをブロックします。クライアントが接続すると、accept() メソッドは新しいソケット オブジェクト client_socket とクライアントのアドレス情報 client_address を返します。
クライアントは client_socket を介してクライアントと通信できます。 client_address には、クライアントの ID を識別するために使用できるクライアントの IP アドレスとポート番号が含まれています。

2.2. クライアントコード client.py

import socket

# 创建socket对象
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 获取服务器的主机名和端口号
host = socket.gethostname()
port = 8888

# 连接到服务器
client_socket.connect((host, port))

# 发送消息给服务器
message = "Hello, 服务器!"
client_socket.send(message.encode())

# 接收服务器发送的响应数据
data = client_socket.recv(1024)

# 处理接收到的响应数据
print("接收到的数据为: ", data.decode())

# 关闭客户端连接
client_socket.close()

1) サーバー コードとの違い:
サーバー コードと比較したクライアント コードの主な違いは、socket.connect() メソッドを使用してサーバーに接続し、socket.send() メソッドを使用して送信することです。一方、サーバー コードは、socket.bind() メソッドを使用して IP アドレスとポート番号をバインドし、socket.listen() メソッドを使用してクライアントの接続要求をリッスンし、次に、socket.accept( ) メソッドを使用してクライアント接続を受け入れ、ソケットを使用します。recv() メソッドは、クライアントによって送信されたメッセージを受信します。
2) message.encode()
message.encode() は、Python の文字列のメソッドであり、文字列をバイト シーケンスにエンコードするために使用されます。Python では、文字列は Unicode エンコードで保存され、ネットワーク送信でデータを送信するためにバイト シーケンスがよく使用されるため、文字列をネットワーク上で送信するには、前にバイト シーケンスにエンコードする必要があります。
message.encode() メソッドは、デフォルトのエンコード方式 (通常は UTF-8 エンコード) に従って文字列メッセージをバイト シーケンスにエンコードし、バイト型のオブジェクトを返します。このバイト オブジェクトは、ソケットの send() メソッドに直接送信して、ネットワークに送信できます。受信側では、受信したバイト シーケンスを、対応するデコード メソッド (サーバー プログラムに登場する bytes.decode() メソッドなど) を使用して文字列にデコードする必要があります。

2.3. 実行方法

使用方法: 2 つのターミナル cmd を使用して 2 つの py ファイル (最初にサーバー、次にクライアント) を実行します。最終的な結果は次のようになります

ここに画像の説明を挿入

クライアント:
ここに画像の説明を挿入

上記のコードは初心者にとって間違いなく多くの問題を引き起こすでしょう。
1) クライアントのポート番号を何に設定する必要がありますか?
ソケット通信では、サーバープログラムまたはクライアントプログラムを識別するためにポート番号が使用されます。サーバー プログラムでは、クライアント プログラムが通信のためにポートに接続できるようにポート番号を指定する必要があります。通常、事前定義されたポート番号をいくつか選択できます。たとえば、HTTP プロトコルのポート番号は 80、SMTP プロトコルのポート番号は 25 などです。ただし、事前定義されたポート番号がすでに使用されている場合、またはアプリケーションに適していない場合は、ポート番号をカスタマイズすることもできます。
提供したコードでは、ポート番号はカスタムであり、必要に応じて設定できます。通常、8888 などの空いているポート番号を選択できます。
2)同様に、クライアントのポート番号も同じ値に設定する必要がありますか?

サーバーのポート番号が 8888 に設定されている場合、クライアントもサーバーに接続するときにポート番号を 8888 に指定する必要があります。このようにして、クライアントは正しいポートに接続し、サーバーと通信できます。ソケット通信では、サーバープログラムまたはクライアントプログラムを識別するためにポート番号が使用されるため、クライアントとサーバー間で通信する場合、接続を正常に確立するにはポート番号が一致している必要があります。

ネットワーク計画に関する補足的な知識

答えの一部は、chatgpt
1)特別なアドレス: 127.0.0.1から得られます。

127.0.0.1 は特別な IP アドレスであり、ローカル ループバック アドレスとも呼ばれます。これはマシンのネットワーク インターフェイスを指します。つまり、このアドレスにアクセスすると、実際にはマシン自体にアクセスすることになります。このアドレスは通常、ネットワーク アプリケーションのテストに使用され、このマシンにサーバー ソフトウェアをインストールするときに、このアドレスをテストに使用できます。たとえば、このマシンに Web サーバーをインストールしている場合、ブラウザを使用して 127.0.0.1 にアクセスし、Web サーバーが正常に動作するかどうかをテストできます。
2)
Host =socket.gethostbyname(socket.gethostname()) と host="127.0.0.1" は同じ意味ですか?
host =socket.gethostbyname(socket.gethostname()) と host="127.0.0.1" はまったく同じではありませんが、どちらもマシンの IP アドレスを指定するために使用できます。
socket.gethostbyname(socket.gethostname()) は、現在のホストの IP アドレスを返します。これは、ローカル エリア ネットワークの IP アドレスまたはパブリック ネットワークの IP アドレスです。コンピュータが LAN に接続されている場合、この IP アドレスを LAN 内での通信に使用できます。
host="127.0.0.1" は、ローカル ループバック アドレス (ループバック アドレス) 127.0.0.1 を使用することを意味します。このアドレスは本機内部でのみ使用できる特殊なIPアドレスであり、ローカルエリアネットワークや公衆ネットワークでの通信には使用できません。
上記のコードでは、socket.gethostbyname(socket.gethostname()) を使用してマシンの IP アドレスを取得し、LAN 内で通信できるようにします。マシン内で通信するだけの場合は、host="127.0.0.1" を使用することもできます。

3) プロセス間通信とソケット通信の違い
プロセス間通信とソケット通信は異なる通信方式であり、実装機構や適用シナリオが異なります。
プロセス間通信 (IPC、Inter-Process Communication) とは、同じコンピュータ上で動作する異なるプロセス間の通信メカニズムを指し、主に同じコンピュータ上の異なるアプリケーション間のデータ送信を実現するために使用されます。IPC メカニズムは、名前付きパイプ、共有メモリ、メッセージ キュー、セマフォなどを介して実装できます。これらはすべて、オペレーティング システムが提供する API を介して実装されます。IPC通信は高速かつ信頼性が高いという利点がありますが、同一のコンピュータ上でしか通信できません。
ソケット通信は、一連の標準的な TCP/IP プロトコルによって実現されるネットワークベースの通信方式で、異なるコンピュータ間でのデータ転送を実現します。ソケット通信はコネクション指向の通信方式であり、通信の過程でコネクションの確立、データの送信、コネクションの切断などの手順が必要となるため、実装はIPCよりも複雑になります。Socket 通信の利点は、異なるコンピュータ間で通信し、ネットワークを越えたデータ転送を実現できることですが、IPC と比較すると、Socket 通信の速度は若干遅くなります。
つまり、プロセス間通信とソケット通信にはそれぞれ長所と短所があり、アプリケーションのシナリオに応じて適切な通信方式を選択する必要があります。同じコンピュータ上でのみ通信する必要がある場合は、IPC メカニズムを選択でき、異なるコンピュータ間で通信する必要がある場合は、ソケット通信を選択できます。

4)ソケット通信とネットワーク通信は概念ですか?

ソケット通信とネットワーク通信は関連する概念ですが、完全に同等ではありません。
ネットワーク通信とは、TCP/IP、HTTP、FTP などのさまざまな通信方法やプロトコルを含む、コンピューター ネットワークを介したデータ送信のプロセスを指します。ネットワーク通信の目的は、あるコンピュータから別のコンピュータにデータを転送し、異なるコンピュータが相互に情報を転送できるようにすることです。
ソケット通信は、一連の標準 TCP/IP プロトコルを通じて実現されるネットワークベースの通信方法です。ソケット通信では、データ送信はネットワーク プロトコル スタックによって処理される必要があります。その中で、TCP/IP プロトコルは最も一般的に使用されるネットワーク プロトコルの 1 つです。ソケット通信はコネクション指向の通信方式であり、通信の過程でコネクションの確立、データの送信、コネクションの切断などの手順が必要となるため、他のネットワーク通信方式に比べ実装が複雑になります。
したがって、ソケット通信は、TCP/IP プロトコルを通じて実現されるネットワーク通信の具体的な実装であると言えますネットワーク通信にはさまざまな通信方式やプロトコルがあり、その実現方式のひとつがソケット通信です。

5) 文字列エンコードとバイトシーケンスは何ですか?
ネットワーク経由でデータを送信する必要がある場合、ネットワーク経由で送信できるようにする前に、データを一連のバイトにエンコードする必要があります。Python では、文字列は Unicode で保存されるため、ネットワーク上で送信するには文字列をバイト シーケンスとしてエンコードする必要があります。
文字列をバイトのシーケンスとしてエンコードする例を次に示します。

s = 「hello world」
b = s.encode()

print(b) # b'hello world'

この例では、まず文字列 s を定義し、次に s.encode() メソッドを使用してそれをバイト シーケンス b にエンコードし、出力します。出力は b'hello world' で、文字列「hello world」がバイト型オブジェクトとしてエンコードされたことを示します。
受信者がバイト シーケンスを受信すると、処理のために文字列にデコードする必要があります。次に、バイト シーケンスを文字列にデコードする例を示します。

b = b'hello world'
s = b.decode()

印刷 # ハローワールド

この例では、まずバイト シーケンス b を定義し、次に b.decode() メソッドを使用してそれを文字列 s にデコードし、出力します。出力は hello world で、バイト シーケンス b'hello world' が文字列「hello world」にデコードされたことを示します。

おすすめ

転載: blog.csdn.net/weixin_46274756/article/details/130146222