python网络:异步握手 [英] python networking: asynchat handshake

查看:55
本文介绍了python网络:异步握手的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 python asynchat 来实现网络协议.在连接时,我需要发送一个命令,服务器通过会话回答.

I am using python asynchat to implement a network protocol. At connection time I need to send a command and the server answer with a session.

我的主要问题是我需要等到收到会话响应.但不确定如何实现这一点.我应该使用 socket.recv 进行连接设置吗?是个好主意吗?

My main problem is that I need to wait until I get the session response. but not sure how to implement this. should I use socket.recv for the connection setup? is a good idea?

推荐答案

在使用异步技术编写网络应用程序时,您等待在某处记录您的状态,然后让主循环继续.在未来的某个时间,您正在等待的数据将可用,主循环将通知您这一事实,您可以将新数据与记录的状态组合以完成您正在处理的任何任务.根据具体的任务,您可能需要多次执行此循环才能真正完成任务.

When writing a network application using asynchronous techniques, you wait by recording your state somewhere and then letting the main loop continue. At some future time, the data you're waiting for will become available, the main loop will notify you of that fact, and you can combine the new data with the recorded state to complete whatever task you are working on. Depending on the specific task, you may need to go through this cycle many times before your task is actually done.

不管你使用什么异步系统,这些想法基本上是一样的.但是,Twisted一个非常优越的系统asynchat,所以我不打算解释任何 asynchat 细节.相反,这是一个使用 Twisted 执行您所询问的事情的示例:

These ideas are basically the same regardless of what asynchronous system you're using. However, Twisted is a vastly superior system to asynchat, so I'm not going to try to explain any of the asynchat details. Instead, here's an example that does the kind of thing you're asking about, using Twisted:

from twisted.internet.defer import Deferred
from twisted.internet.protocol import Protocol, Factory
from twisted.internet.endpoints import TCP4ClientEndpoint
from twisted.internet import reactor

# Stream-oriented connections like TCP are handled by an instance 
# of a Protocol subclass
class SomeKindOfClient(Protocol):

     # When a new connection is established, the first thing that
     # happens is this method is called.
     def connectionMade(self):
         # self.transport is set by the superclass, and lets us 
         # send data over the connection
         self.transport.write("GREETING")

         # a Deferred is a generic, composable API for specifying
         # callbacks
         self.greetingComplete = Deferred()

         # Here's some local state
         self._buffer = ""

     # Whenever bytes arrive on the TCP connection, they're passed
     # to this method
     def dataReceived(self, bytes):

         # Incorportate the network event data into our local state.
         #  This kind of buffering is always necessary with TCP, because
         # there's no guarantees about how many bytes will be delivered
         # at once (except that it will be at least 1), regardless of
         # the size of the send() the peer did.
         self._buffer += bytes

         # Figure out if we're done - let's say the server response is 32
         # bytes of something
         if len(self._buffer) >= 32:
             # Deliver it to whomever is waiting, by way of the Deferred
             # object
             greeting, self._buffer = self._buffer[:32], self._buffer[32:]
             complete = self.greetingComplete
             self.greetingComplete = None
             complete.callback(greeting)

         # Otherwise we'll keep waiting until dataReceived is called again
         # and we have enough bytes.


# One of the normal ways to create a new client connection
f = Factory()
f.protocol = SomeKindOfClient
e = TCP4ClientEndpoint(reactor, "somehost", 1234)

# Connect returns one of those Deferreds - letting us specify a function
# to call when the connection is established.  The implementation of
# connect is also doing basically the same kind of thing as you're asking
# about.
d = e.connect(f)

# Execution continues to this point before the connection has been
# established.  Define a function to use as a callback when the connection
# does get established.
def connected(proto):
    # proto is an instance of SomeKindOfClient.  It has the 
    # greetingComplete attribute, which we'll attach a callback to so we
    # can "wait" for the greeting to be complete.
    d = proto.greetingComplete

    def gotGreeting(greeting):
        # Note that this is really the core of the answer.  This function
        # is called *only* once the protocol has decided it has received
        # some necessary data from the server.  If you were waiting for a
        # session identifier of some sort, this is where you might get it
        # and be able to proceed with the remainder of your application
        # logic.
        print "Greeting arrived", repr(greeting)

    # addCallback is how you hook a callback up to a Deferred - now
    # gotGreeting will be called when d "fires" - ie, when its callback
    # method is invoked by the dataReceived implementation above.
    d.addCallback(gotGreeting)

# And do the same kind of thing to the Deferred we got from 
# TCP4ClientEndpoint.connect
d.addCallback(connected)

# Start the main loop so network events can be processed
reactor.run()

要查看它的行为方式,您可以启动一个简单的服务器(例如 nc -l 1234)并将客户端指向它.你会看到问候语到达,你可以发回一些字节.一旦您发回 30,客户端将打印它们(然后无限期地挂起,因为我没有在该协议中实现进一步的逻辑).

To see how this behaves, you can launch a simple server (eg nc -l 1234) and point the client at it. You'll see the greeting arrive and you can send some bytes back. Once you've sent back 30, the client will print them (and then hang around indefinitely, because I implemented no further logic in that protocol).

这篇关于python网络:异步握手的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆