ホームページ >バックエンド開発 >Python チュートリアル >Pythonの高度なソケットの詳細な説明

Pythonの高度なソケットの詳細な説明

高洛峰
高洛峰オリジナル
2016-10-17 16:13:551033ブラウズ

英語のSocketの本来の意味は「穴」「ソケット」です。 BSD UNIX のプロセス通信メカニズムとして、一般に「ソケット」とも呼ばれます。これは、IP アドレスとポートを記述するために使用され、通信チェーンのハンドルであり、異なる仮想マシンまたは異なるコンピューター間の通信を実装するために使用できます。 。

ネットワーク上の 2 つのプログラムは、双方向通信接続を通じてデータを交換します。この接続の一端はソケットと呼ばれます。

ネットワーク通信接続を確立するには、少なくとも 1 組のポート番号 (ソケット) が必要です。ソケットは本質的には TCP/IP をカプセル化するプログラミング インターフェイス (API) であり、TCP/IP はプログラマーがネットワーク開発に使用するインターフェイスも提供します。これは、ソケット プログラミング インターフェイスであり、カプセル化または表示する手段を提供します。データ。ソケットはネットワーク通信機能を提供します。

Pythonのソケットについて話しましょう。

1.socketモジュール

ソケットを作成するにはsocket.socket()関数を使用します。構文は次のとおりです:

socket.socket(socket_family,socket_type,protocol=0)


socket_family には次のパラメータを指定できます:


socket.AF_INET IPv4 (デフォルト) ocket.AF_INET 6 IPv6


socket.af_unix単一のunix systemsocket_typeでのプロセス間通信にのみ使用できます。 )

socket.SO CK_DGRAM Data Report ソケット、UDP 用


socket.SOCK_RAW raw ソケット、通常のソケットは ICMP や IGMP などのネットワーク メッセージを処理できませんが、SOCK_RAW は第二に、SOCK_RAW は特殊な IPv4 メッセージも処理できます。さらに、生のソケットを使用すると、ユーザーが IP_HDRINCL ソケット オプションを使用して IP ヘッダーを構築できます。

socket.SOCK_RDM は UDP の信頼できる形式であり、データグラムの配信を保証しますが、順序は保証しません。 SOCK_RAM は、元のプロトコルへの低レベルのアクセスを提供するために使用され、ICMP メッセージの送信など、特定の特殊な操作を実行する必要がある場合に使用されます。通常、SOCK_RAM はパワー ユーザーまたは管理者によって実行されるプログラムに制限されます。

socket.SOCK_SEQPACKET 信頼性の高い連続データパケットサービス

プロトコルパラメータ:

0 (デフォルト) 0の場合、システムはアドレスフォーマットに従って設定します。カテゴリを接続し、適切なプロトコルを自動選択


2.ソケットオブジェクト組み込みメソッド


サーバー側ソケット関数

s.bind() アドレス(ipアドレス、ポート)をバインドソケットに渡す場合、パラメーターはタプルの形式である必要があります。例: s.bind(('127.0.0.1',8009))

s.listen(5) リスニングを開始します。5 が最大値です。 Hang 接続数

s.accept() クライアント接続を受動的に受け入れる、ブロックする、接続を待つ

クライアントソケット関数

s.connect() サーバーに接続する、パラメータタプル形式です。例: s.connect(('127,0.0.1',8009))

公共目的ソケット関数

s.recv(1024) TCP 受信data, 1024 1回のデータ受信のサイズです

s.send(bytes) TCPデータを送信するには、python3で送信するデータの形式がbytes形式である必要があります

s.sendall()データを完全に削除したら、内側のループでsend

を呼び出します

s.close() ソケットを閉じる

例1. ソケットプログラムの簡単な実装

サーバー側

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
import socket
import time
IP_PORT = ('127.0.0.1',8009)
BUF_SIZE = 1024
  
tcp_server = socket.socket()
tcp_server.bind(IP_PORT)
tcp_server.listen(5)
  
while True:
    print("waiting for connection...")
    conn,addr = tcp_server.accept()
    print("...connected from:",addr)
    while True:
        data = tcp_server.recv(BUF_SIZE)
        if not data:break
        tcp_server.send('[%s] %s'%(time.ctime(),data))
  
tcp_server.close()


上記の説明コード:


1~4行

最初の行はUnix起動情報行で、その後にtimeモジュールとsocketモジュールがインポートされます

5~10行

IP_PORT は、グローバル変数の IP アドレスとポートを宣言し、bind() 関数がこのアドレスにバインドし、バッファ サイズを 1K に設定することを示します。 listen() 関数は、同時に受信できる接続の最大数を示します。それ以降のものは拒否されます

11~最後の行に移動

サーバーのループに入った後、受動的に接続が到着するのを待ちます。接続がある場合は、会話ループに入り、クライアントがデータを送信するのを待ちます。メッセージが空の場合は、クライアントが終了したことを意味し、ループから抜け出して次の接続の到着を待ちます。クライアント メッセージを取得したら、メッセージの前にタイムスタンプを追加して戻ります。ループが終了せず、サーバーが close() を実行しないため、最後の行は実行されません。 close() 関数を呼び出すことを忘れないように注意してください。

クライアント

#!/usr/bin/env python

# _*_ coding:utf-8 _*_
import socket
  
HOST = '127.0.0.1'
PORT = 8009
BUF_SIZE = 1024
ADDR = (HOST,PORT)
  
client = socket.socket()
client.connect(ADDR)
  
while True:
    data = input(">>> ")
    if not data:break
    client.send(bytes(data,encoding='utf-8'))
    recv_data = client.recv(BUF_SIZE)
    if not recv_data:break
    print(recv_data.decode())
      
client.close()

5~11行

HOST和PORT变量表示服务器的IP地址与端口号。由于演示是在同一台服务器所以IP地址都是127.0.0.1,如果运行在其他服务器上要做相应的修改。端口号要与服务器端完全相同否则无法通信。缓冲区大小还是1K。


客户端套接字在10行创建然后就去连接服务器端


13~21行


客户端也无限循环,客户端的循环在以下两个条件的任意一个发生后就退出:1.用户输入为空的情况或者服务器端响应的消息为空。否则客户端会把用户输入的字符串发送给服务器进行处理,然后接收显示服务器返回来的带有时间戳的字符串。


运行客户端程序与服务端程序


以下是客户端的输入与输出

[root@pythontab]# python client.py 
>>> hello python
[Thu Sep 15 22:29:12 2016] b'hello python'

   


以下是服务端输出

[root@pythontab]# python server.py 
waiting for connection...
...connected from: ('127.0.0.1', 55378)

   

3.socketserver模块

socketserver是标准库中的一个高级别的模块。用于简化实现网络客户端与服务器所需要的大量样板代码。模块中已经实现了一些可以使用的类。


实例1:使用socketserver实现与上面socket()实例一样的功能


服务端程序代码

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
import socketserver
import time
  
HOST = '127.0.0.1'
PORT = 8009
ADDR = (HOST,PORT)
BUF_SIZE = 1024
  
class Myserver(socketserver.BaseRequestHandler):
    def handle(self):
        while True:
            print("...connected from:",self.client_address)
            data = self.request.recv(BUF_SIZE)
            if not data:break
            self.request.send(bytes("%s %s"%(time.ctime(),data)))
  
server = socketserver.ThreadingTCPServer(ADDR,Myserver)
print("waiting for connection...")
server.serve_forever()

   


11~17行


主要的工作在这里。从socketserver的BaseRequestHandler类中派生出一个子类,并重写handle()函数。


在有客户端发进来的消息的时候,handle()函数就会被调用。


19~21行


代码的最后一部分用给定的IP地址和端口加上自定义处理请求的类(Myserver)。然后进入等待客户端请求与处理客户端请求的无限循环中。


客户端程序代码

import socket
HOST = '127.0.0.1'
PORT = 8009
ADDR = (HOST,PORT)
BUF_SIZE = 1024
  
client = socket.socket()
client.connect(ADDR)
  
while True:
    data = input(">>> ")
    if not data:continue
    client.send(bytes(data,encoding='utf-8'))
    recv_data = client.recv(BUF_SIZE)
    if not recv_data:break
    print(recv_data.decode())
  
client.close()

   

执行服务端和客户端代码  


下面是客户端输出

[root@pythontab]# python socketclient.py 
>>> hello python
Thu Sep 15 23:53:31 2016 b'hello python'
>>> hello pythontab
Thu Sep 15 23:53:49 2016 b'hello pythontab'

   


下面是服务端输出

[root@pythontab]# python socketserver.py 
waiting for connection...
...connected from: ('127.0.0.1', 55385)
...connected from: ('127.0.0.1', 55385)
...connected from: ('127.0.0.1', 55385)
...connected from: ('127.0.0.1', 55385)


   


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。