3

server.py と client.py の 2 つのファイルがあり、どちらも asyncore.dispatcher を使用して作成されています。

サーバー.py

import asyncore, socket

class Server(asyncore.dispatcher):
    def __init__(self, host, port):
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.bind(('', port))
        self.listen(1)
        print "Waiting for connection..."

    def handle_accept(self):
        socket, address = self.accept()
        print 'Connection by', address
        socket.send("Hello Server")

    def handle_read(self):
        print "Reading..."
        out_buffer = self.recv(1024)
        if not out_buffer:
            self.close()
        print out_buffer

    def handle_closed(self):
        print "Server: Connection Closed"
        self.close()

s = Server('0.0.0.0', 5007)
asyncore.loop()

Client.py

import asyncore, socket

class Client(asyncore.dispatcher):
    def __init__(self, host, port):
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.connect((host, port))
        print "Client Start..."

    def handle_close(self):
        print "Client: Connection Closed"
        self.close()

    def handle_read(self):
        data = self.recv(1024)
        if data:
            print "Received ", data
        self.send("Hello Client")

c = Client('127.0.0.1', 5007)
asyncore.loop()

結果:

実行server.py:

Waiting for connection...

次にclient.py

Client Start...
Received  Hello Server
Client: Connection Closed
Client: Connection Closed

最後に client.py が終了し、server.py の出力ウィンドウにもう 1 行表示され、サーバーは引き続き実行されます。

Connection by ('127.0.0.1', 58197)

理解できないことがあります:

  1. client.pyの関数handle_closedが2 回実行されるのはなぜですか?

  2. server.pyhandle_readingの関数が実行されないのはなぜですか? client.pyはメッセージ ("Hello Client") を送信しましたが、サーバーがそれを受信できないのはなぜですか?

  3. server.pyhandle_closedの関数が実行されないのはなぜですか? クライアントの終了時にserver.pyでいくつかのコードを実行したいのですが、server.pyでは何もしないようです。handle_closed

4

3 に答える 3

9

アシンコアトーク

handle_read()in server.py が呼び出されることはありません。

しかし、なぜ?!それはサーバークラスです...

はい。ただし、クラスは確立されていない接続をリッスンServerするためにソケットを使用します。その上でのすべての読み取りは に送られ、実際のチャネル ソケット (何らかのエンドポイントに接続されている) が、継承されたクラスの新しいインスタンス (できれば) に与えられる必要があります。あなたのメソッドでは、取得したソケットはローカルであったため、この関数を終了すると削除されたため、新しい接続が受け入れられ、テキストが送信された後、そのソケットはすぐに強制終了されました。handle_accept()dispatcherServerhandle_accept()accept()

asyncore モジュールと他の質問の私の回答を読んでください。

サーバ

先ほど言ったように、server.py で接続用の新しいクラスを作成する必要があります。

class ClientHandler(asyncore.dispatcher):
    def handle_read(self):
        data = self.recv(1024)
        if not data:
            return
        print "Received:", data

    def handle_close(self):
        print "Server: Connection Closed"
        self.close()

ここで、null が受信されたときに手動でソケットを閉じる必要がないことに注意してくださいasyncore。接続を適切に閉じます。

次にServer、接続が確立されたときにインスタンス化する必要があります。

    def handle_accept(self):
        ...
        ClientHandler(socket)

Server- メソッドの固有名はでスペルミスもしましたhandle_close。それは役に立たないでしょうが。クライアント接続に関連するものはすべて にありますClientHandler

クライアント

client.py では、次のように変更するだけですhandle_read()

    if data:
        print "Received ", data

への変更:

    if not data:
        return
    print "Received ", data

なんで?これsend()がないと、ソケットが実際に閉じられている場合でもhandle_close()呼び出され、asyncore. 私が言ったように-asyncoreこれを処理します。

ノート

これで、接続用のより複雑なサーバー側クラスを作成できます。また、OS レベルのソケットがどのように機能するかを学ぶこともできるので、トラブルに巻き込まれることはありません。

asyncoreそれ自体はソケットの非常に優れたラッパーですが、イベント駆動型環境での HTTP や SMTP 処理など、より高度な処理を行いたい場合は、Twistedライブラリに興味があるでしょう!

于 2013-08-03T21:01:22.920 に答える
0

機能させるには、関数handle_read()を定義する必要がありreadable()ます。この関数は、Trueまたはを返す必要がありますFalse。この関数をコードに追加すると問題が解決すると思います:

def readable(self):
    return True

いくつかの例と詳細については、次のリンクを参照してください: https://parijatmishra.wordpress.com/2008/01/04/writing-a-server-with-pythons-asyncore-module/

于 2015-07-28T01:50:45.647 に答える