Python论坛  - 讨论区

标题:[python-chinese] twisted中的udp客户端,如何在reactor中连接另外一个ip地址,或者断开连接呢?

2005年07月26日 星期二 22:15

梅劲松  stephen.cn at gmail.com
Tue Jul 26 22:15:11 HKT 2005

twisted中的udp客户端,如何在reactor中连接另外一个ip地址,或者断开连接呢?
比如我连接了1.1.1.1的4000端口,但是我这个时候需要端开连接,并连接到2.2.2.2的5000端口,应该怎么做呢?


-- 
梅劲松

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2005年07月27日 星期三 08:42

梅劲松  stephen.cn at gmail.com
Wed Jul 27 08:42:19 HKT 2005

因为在transport没有发现相应的操作,我用reactor.stop()来停止了后,全局变量改变服务器的值,但是新的reactor.run()则运行不起来了。
代码如下:
# -*- coding: cp936 -*-

from qq.message import qqmsg
from qq.protocols import qqp
from twisted.internet import reactor, protocol, defer, threads
from time import clock
import Queue
import md5
import util,struct,tea

import time

from binascii import b2a_hex, a2b_hex

import basic

import string, sys

# 定义了滑动窗口的大小
WINMAX = 1024

class qq:
    #建立QQ用户对象
    def __init__(self,id,pwd):
        self.id=id
        self.pwd=pwd
        self.initkey=''
        self.md5pwd=''
        #初始化会话密钥,因为使用会话密钥最多,所以这里初始化,用于解密时进行判断。
        self.session=chr(00)*16
        #发送消息id需要变化
        self.session_id = 0
        self.friend_list={}
        self.friend_online={}
        self.start()
        
    def start(self):
        self.initkey=util.initkey()
        self.md5pwd=md5.new(md5.new(self.pwd).digest()).digest()
        
class qqClientProtocol(qqp.qqClientQueueProtocol):
    """建立一个qq客户机的协议处理"""
    def __init__(self,qq):
        # 滑动窗口的大小
        self.WINMAX = WINMAX
        # 等待发送的报文队列
        self.sendQueue = Queue.Queue(self.WINMAX)
        # 已经发出的报文序列ID
        self.sendMsg = []
        # 已经接受的报文序列ID
        self.recvMsg = []
        # 使用的消息ID
        self.sequence = 1
        #使用qq属性
        self.qq=qq

    def goip(self,domain):#解析域名到ip
        return reactor.resolve(domain).result

    def startProtocol(self):
        """连接成功后开始发送报文"""
        reactor.callInThread(self.input)

    def login(self):
        print '开始连接服务器219.133.38.165'
	self.transport.connect("219.133.38.165",8000)
        self.on_qq_connect()
        
    def on_qq_connect(self):
        # 先发一个connect报文进行握手
        message = qqmsg.outqqMessage(self.qq)
        message.setMsgName('qq_pre_login')
        message.body.setField('unknown',0)
        self.sendDataToQueue(message)
        qqp.qqClientQueueProtocol.connectionMade(self)
        

    def on_qq_pre_login(self,message):
        # 显示服务器发送过来的令牌,并构造登陆报文。
        status=message.body.fields['status']
        pre_len=message.body.fields['pre_len']
        pre=message.body.fields['pre']
        if status != 0:
            print '申请登陆令牌错!'
        message = qqmsg.outqqMessage(self.qq)
        message.setMsgName('qq_login')
        message.body.setField('initkey',self.qq.initkey)
        message.body.setField('md5',tea.encrypt('',self.qq.md5pwd))
        message.body.setField('16_51',a2b_hex(basic.QQ_login_16_51))
        message.body.setField('login_status',chr(basic.QQ_login['normal']))
        message.body.setField('53_68',a2b_hex(basic.QQ_login_53_68))
        message.body.setField('pre_len',chr(pre_len))
        message.body.setField('pre',pre[0])
        message.body.setField('unknown',chr(0x40))
        message.body.setField('login_end',a2b_hex(basic.QQ_login_end))
        message.body.setField('end',(416-len(message.body))*chr(00))
        self.sendDataToQueue(message)

    def on_qq_login(self,message):
        if message.body.fields['status'][0]==1:
            #self.transport.connect(util.ip2string(message.body.fields['ip']),8000)
            print '需要重定向ip到:'+util.ip2string(message.body.fields['ip'])
        if message.body.fields['status'][0]==5:
            print message.body.fields['data'][0]
        else:
            self.qq.session=message.body.fields['session']
            message = qqmsg.outqqMessage(self.qq)
            message.setMsgName('qq_chang_status')
            send_data = str(basic.QQ_status['online'])+basic.QQ_video
            send_data = tea.encrypt(send_data,self.qq.session)
            message.body.setField('data',send_data)
            self.sendDataToQueue(message)

    def on_qq_chang_status(self, message):
        print "您当前的状态为:在线"
        #开始每隔1分钟发送一次在线包
        defer.succeed(self.alive())

    def alive(self):
        message = qqmsg.outqqMessage(self.qq)
        message.setMsgName('qq_alive')
        message.body.setField('qq',str(self.qq.id))
        self.sendDataToQueue(message)
        reactor.callLater(60, self.alive)
        
    def on_qq_alive(self, message):
        if message.body.fields['data'][0][0]!= '0':
            print "发送活动维持包失败"

    def on_qq_get_friend_list(self, message):
        if message.body.fields['start'][0]!=65535:
            defer.succeed(self.get_friend_list(message.body.fields['start'][0]))
            self.qq.friend_list.update(message.body.fields['data'].items())

        else:
            self.qq.friend_list.update(message.body.fields['data'].items())
            print "您的好友列表:"
            for i in self.qq.friend_list.keys():
                print str(i)+':'+self.qq.friend_list[i]['name']

    def on_qq_get_friend_online(self, message):
        if message.body.fields['start'][0]!=255:
            defer.succeed(self.get_friend_online(message.body.fields['start'][0]))
            self.qq.friend_online.update(message.body.fields['data'].items())

        else:
            self.qq.friend_online.update(message.body.fields['data'].items())
            print "您的在线好友列表:"
            for i in self.qq.friend_online.keys():
                print str(i)+':'+self.qq.friend_list[i]['name']

    def send_msg(self, recv_qq, msg):
        message = qqmsg.outqqMessage(self.qq)
        message.setMsgName('qq_send')
        self.qq.session_id += 1
        message.body.setField('send_qq',self.qq.id)
        message.body.setField('recv_qq',recv_qq)
        message.body.setField('ver',basic.QQ_ver)
        message.body.setField('send_qq1',self.qq.id)
        message.body.setField('recv_qq1',recv_qq)
        message.body.setField('md5',md5.new(str(self.qq.id)+self.qq.session).digest())
        message.body.setField('type',11)
        message.body.setField('session_id',self.qq.session_id)
        message.body.setField('send_time',recv_qq)
        message.body.setField('send_face',0)
        message.body.setField('font_info',1)
        message.body.setField('msg_pass',1)
        message.body.setField('msg_id',1)
        message.body.setField('msg_type',1)
        message.body.setField('msg_data',msg)
        message.body.setField('msg_link',' '+chr(00))
        message.body.setField('msg_end',9)
        message.body.setField('msg_red',0)
        message.body.setField('msg_green',0)
        message.body.setField('msg_blue',0)
        message.body.setField('unknown',0)
        message.body.setField('encoding',0x8602)
        message.body.setField('info',a2b_hex('cbcecce5'))
        #尾部分长度固定为9
        message.body.setField('len',len(message.body.fields['msg_data'])+9)
        self.sendDataToQueue(message)

    def get_friend_list(self, start):
        message = qqmsg.outqqMessage(self.qq)
        message.setMsgName('qq_get_friend_list')
        message.body.setField('start', start)
        message.body.setField('sorted',basic.QQ_friend_list_sorted)
        self.sendDataToQueue(message)

    def get_friend_online(self, start):
        message = qqmsg.outqqMessage(self.qq)
        message.setMsgName('qq_get_friend_online')
        message.body.setField('type', 0x02)
        message.body.setField('start', start)
        message.body.setField('unknown',0)
        message.body.setField('unknown1',0)
        self.sendDataToQueue(message)
    
    def on_qq_send(self, message):
        print message.body

    def on_qq_recv(self, message):
        #将收到的消息的前16位返回给服务器,表示已经收到消息
        try:
            print
self.qq.friend_list[message.body.fields['send_qq']]['name']+':'+\
                message.body.fields['msg_data']
        except KeyError:
            print str(message.body.fields['send_qq'])+':'+\
                message.body.fields['msg_data']
            
            
        send_qq = message.body.fields['send_qq']
        recv_qq = message.body.fields['recv_qq']
        msg_id = message.body.fields['msg_id']
        send_ip = message.body.fields['send_ip']
        #将接受到的流水号发送出去。
        sequence = message.head.sequence
        message = qqmsg.outqqMessage(self.qq)
        message.head.sequence = sequence
        message.setMsgName('qq_recv')
        message.body.setField('send_qq',send_qq)
        message.body.setField('recv_qq',recv_qq)
        message.body.setField('msg_id',msg_id)
        message.body.setField('send_ip',send_ip)
        self.sendDataToQueue(message)

    def cmd(self,cmd):
        cmd = string.split(cmd,'/')
        if cmd[0]=='login':
            defer.succeed(self.login())
        if cmd[0]=='send':
            if len(cmd) != 3:
                print "输入命令不完整"
            else:
                defer.succeed(self.send_msg(int(cmd[1]),cmd[2]))
        if cmd[0]=='list':
            self.qq.friend_list.clear()
            defer.succeed(self.get_friend_list(0))
        if cmd[0]=='online':
            if len(self.qq.friend_list) == 0:
                print "请先用list命令获取你的好友列表。"
            else:
                self.qq.friend_online.clear()
                defer.succeed(self.get_friend_online(0))    
        else:
            print "请输入命令,参数间隔请使用/符号,例如send/278333853/你好!"
        reactor.callLater(0, self.input)

    def input(self):
        #获取命令
        cmd = threads.deferToThread(raw_input, "Python-QQ:")
        cmd.addCallback(self.cmd)


    
def main():
    nownum = 0
    lastuid = ''
    getnum = 0
    
    qq_user=qq(476705269,'python')
    reactor.listenUDP(0, qqClientProtocol(qq_user))
    start = clock()
    reactor.run()
    "测试数据:%10d 条" %nownum
    print "收到 %d 条" %getnum
    print "最后收到uid为:%s" %lastuid
    print "用时:%.2f 秒" %(clock()-start)
    print "每秒:%f条" %(nownum / (clock()-start))

if __name__ == "__main__":
    main()



在 05-7-26,梅劲松<stephen.cn at gmail.com> 写道:
> twisted中的udp客户端,如何在reactor中连接另外一个ip地址,或者断开连接呢?
> 比如我连接了1.1.1.1的4000端口,但是我这个时候需要端开连接,并连接到2.2.2.2的5000端口,应该怎么做呢?
> 
> 
> --
> 梅劲松
> 


-- 
梅劲松

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2005年07月27日 星期三 10:26

梅劲松  stephen.cn at gmail.com
Wed Jul 27 10:26:25 HKT 2005

在Jerry Marx的帮助下,问题搞定了。
不使用connent连接到指定ip和端口,而用成发送。
def sendData(self, data):
        """将报文发送出去"""
        self.transport.write(data, self.qq.server)
这样就可以了

在 05-7-27,梅劲松<stephen.cn at gmail.com> 写道:
> 因为在transport没有发现相应的操作,我用reactor.stop()来停止了后,全局变量改变服务器的值,但是新的reactor.run()则运行不起来了。
> 代码如下:
> # -*- coding: cp936 -*-
> 
> from qq.message import qqmsg
> from qq.protocols import qqp
> from twisted.internet import reactor, protocol, defer, threads
> from time import clock
> import Queue
> import md5
> import util,struct,tea
> 
> import time
> 
> from binascii import b2a_hex, a2b_hex
> 
> import basic
> 
> import string, sys
> 
> # 定义了滑动窗口的大小
> WINMAX = 1024
> 
> class qq:
>    #建立QQ用户对象
>    def __init__(self,id,pwd):
>        self.id=id
>        self.pwd=pwd
>        self.initkey=''
>        self.md5pwd=''
>        #初始化会话密钥,因为使用会话密钥最多,所以这里初始化,用于解密时进行判断。
>        self.session=chr(00)*16
>        #发送消息id需要变化
>        self.session_id = 0
>        self.friend_list={}
>        self.friend_online={}
>        self.start()
> 
>    def start(self):
>        self.initkey=util.initkey()
>        self.md5pwd=md5.new(md5.new(self.pwd).digest()).digest()
> 
> class qqClientProtocol(qqp.qqClientQueueProtocol):
>    """建立一个qq客户机的协议处理"""
>    def __init__(self,qq):
>        # 滑动窗口的大小
>        self.WINMAX = WINMAX
>        # 等待发送的报文队列
>        self.sendQueue = Queue.Queue(self.WINMAX)
>        # 已经发出的报文序列ID
>        self.sendMsg = []
>        # 已经接受的报文序列ID
>        self.recvMsg = []
>        # 使用的消息ID
>        self.sequence = 1
>        #使用qq属性
>        self.qq=qq
> 
>    def goip(self,domain):#解析域名到ip
>        return reactor.resolve(domain).result
> 
>    def startProtocol(self):
>        """连接成功后开始发送报文"""
>        reactor.callInThread(self.input)
> 
>    def login(self):
>        print '开始连接服务器219.133.38.165'
>        self.transport.connect("219.133.38.165",8000)
>        self.on_qq_connect()
> 
>    def on_qq_connect(self):
>        # 先发一个connect报文进行握手
>        message = qqmsg.outqqMessage(self.qq)
>        message.setMsgName('qq_pre_login')
>        message.body.setField('unknown',0)
>        self.sendDataToQueue(message)
>        qqp.qqClientQueueProtocol.connectionMade(self)
> 
> 
>    def on_qq_pre_login(self,message):
>        # 显示服务器发送过来的令牌,并构造登陆报文。
>        status=message.body.fields['status']
>        pre_len=message.body.fields['pre_len']
>        pre=message.body.fields['pre']
>        if status != 0:
>            print '申请登陆令牌错!'
>        message = qqmsg.outqqMessage(self.qq)
>        message.setMsgName('qq_login')
>        message.body.setField('initkey',self.qq.initkey)
>        message.body.setField('md5',tea.encrypt('',self.qq.md5pwd))
>        message.body.setField('16_51',a2b_hex(basic.QQ_login_16_51))
>        message.body.setField('login_status',chr(basic.QQ_login['normal']))
>        message.body.setField('53_68',a2b_hex(basic.QQ_login_53_68))
>        message.body.setField('pre_len',chr(pre_len))
>        message.body.setField('pre',pre[0])
>        message.body.setField('unknown',chr(0x40))
>        message.body.setField('login_end',a2b_hex(basic.QQ_login_end))
>        message.body.setField('end',(416-len(message.body))*chr(00))
>        self.sendDataToQueue(message)
> 
>    def on_qq_login(self,message):
>        if message.body.fields['status'][0]==1:
>            #self.transport.connect(util.ip2string(message.body.fields['ip']),8000)
>            print '需要重定向ip到:'+util.ip2string(message.body.fields['ip'])
>        if message.body.fields['status'][0]==5:
>            print message.body.fields['data'][0]
>        else:
>            self.qq.session=message.body.fields['session']
>            message = qqmsg.outqqMessage(self.qq)
>            message.setMsgName('qq_chang_status')
>            send_data = str(basic.QQ_status['online'])+basic.QQ_video
>            send_data = tea.encrypt(send_data,self.qq.session)
>            message.body.setField('data',send_data)
>            self.sendDataToQueue(message)
> 
>    def on_qq_chang_status(self, message):
>        print "您当前的状态为:在线"
>        #开始每隔1分钟发送一次在线包
>        defer.succeed(self.alive())
> 
>    def alive(self):
>        message = qqmsg.outqqMessage(self.qq)
>        message.setMsgName('qq_alive')
>        message.body.setField('qq',str(self.qq.id))
>        self.sendDataToQueue(message)
>        reactor.callLater(60, self.alive)
> 
>    def on_qq_alive(self, message):
>        if message.body.fields['data'][0][0]!= '0':
>            print "发送活动维持包失败"
> 
>    def on_qq_get_friend_list(self, message):
>        if message.body.fields['start'][0]!=65535:
>            defer.succeed(self.get_friend_list(message.body.fields['start'][0]))
>            self.qq.friend_list.update(message.body.fields['data'].items())
> 
>        else:
>            self.qq.friend_list.update(message.body.fields['data'].items())
>            print "您的好友列表:"
>            for i in self.qq.friend_list.keys():
>                print str(i)+':'+self.qq.friend_list[i]['name']
> 
>    def on_qq_get_friend_online(self, message):
>        if message.body.fields['start'][0]!=255:
>            defer.succeed(self.get_friend_online(message.body.fields['start'][0]))
>            self.qq.friend_online.update(message.body.fields['data'].items())
> 
>        else:
>            self.qq.friend_online.update(message.body.fields['data'].items())
>            print "您的在线好友列表:"
>            for i in self.qq.friend_online.keys():
>                print str(i)+':'+self.qq.friend_list[i]['name']
> 
>    def send_msg(self, recv_qq, msg):
>        message = qqmsg.outqqMessage(self.qq)
>        message.setMsgName('qq_send')
>        self.qq.session_id += 1
>        message.body.setField('send_qq',self.qq.id)
>        message.body.setField('recv_qq',recv_qq)
>        message.body.setField('ver',basic.QQ_ver)
>        message.body.setField('send_qq1',self.qq.id)
>        message.body.setField('recv_qq1',recv_qq)
>        message.body.setField('md5',md5.new(str(self.qq.id)+self.qq.session).digest())
>        message.body.setField('type',11)
>        message.body.setField('session_id',self.qq.session_id)
>        message.body.setField('send_time',recv_qq)
>        message.body.setField('send_face',0)
>        message.body.setField('font_info',1)
>        message.body.setField('msg_pass',1)
>        message.body.setField('msg_id',1)
>        message.body.setField('msg_type',1)
>        message.body.setField('msg_data',msg)
>        message.body.setField('msg_link',' '+chr(00))
>        message.body.setField('msg_end',9)
>        message.body.setField('msg_red',0)
>        message.body.setField('msg_green',0)
>        message.body.setField('msg_blue',0)
>        message.body.setField('unknown',0)
>        message.body.setField('encoding',0x8602)
>        message.body.setField('info',a2b_hex('cbcecce5'))
>        #尾部分长度固定为9
>        message.body.setField('len',len(message.body.fields['msg_data'])+9)
>        self.sendDataToQueue(message)
> 
>    def get_friend_list(self, start):
>        message = qqmsg.outqqMessage(self.qq)
>        message.setMsgName('qq_get_friend_list')
>        message.body.setField('start', start)
>        message.body.setField('sorted',basic.QQ_friend_list_sorted)
>        self.sendDataToQueue(message)
> 
>    def get_friend_online(self, start):
>        message = qqmsg.outqqMessage(self.qq)
>        message.setMsgName('qq_get_friend_online')
>        message.body.setField('type', 0x02)
>        message.body.setField('start', start)
>        message.body.setField('unknown',0)
>        message.body.setField('unknown1',0)
>        self.sendDataToQueue(message)
> 
>    def on_qq_send(self, message):
>        print message.body
> 
>    def on_qq_recv(self, message):
>        #将收到的消息的前16位返回给服务器,表示已经收到消息
>        try:
>            print
> self.qq.friend_list[message.body.fields['send_qq']]['name']+':'+\
>                message.body.fields['msg_data']
>        except KeyError:
>            print str(message.body.fields['send_qq'])+':'+\
>                message.body.fields['msg_data']
> 
> 
>        send_qq = message.body.fields['send_qq']
>        recv_qq = message.body.fields['recv_qq']
>        msg_id = message.body.fields['msg_id']
>        send_ip = message.body.fields['send_ip']
>        #将接受到的流水号发送出去。
>        sequence = message.head.sequence
>        message = qqmsg.outqqMessage(self.qq)
>        message.head.sequence = sequence
>        message.setMsgName('qq_recv')
>        message.body.setField('send_qq',send_qq)
>        message.body.setField('recv_qq',recv_qq)
>        message.body.setField('msg_id',msg_id)
>        message.body.setField('send_ip',send_ip)
>        self.sendDataToQueue(message)
> 
>    def cmd(self,cmd):
>        cmd = string.split(cmd,'/')
>        if cmd[0]=='login':
>            defer.succeed(self.login())
>        if cmd[0]=='send':
>            if len(cmd) != 3:
>                print "输入命令不完整"
>            else:
>                defer.succeed(self.send_msg(int(cmd[1]),cmd[2]))
>        if cmd[0]=='list':
>            self.qq.friend_list.clear()
>            defer.succeed(self.get_friend_list(0))
>        if cmd[0]=='online':
>            if len(self.qq.friend_list) == 0:
>                print "请先用list命令获取你的好友列表。"
>            else:
>                self.qq.friend_online.clear()
>                defer.succeed(self.get_friend_online(0))
>        else:
>            print "请输入命令,参数间隔请使用/符号,例如send/278333853/你好!"
>        reactor.callLater(0, self.input)
> 
>    def input(self):
>        #获取命令
>        cmd = threads.deferToThread(raw_input, "Python-QQ:")
>        cmd.addCallback(self.cmd)
> 
> 
> 
> def main():
>    nownum = 0
>    lastuid = ''
>    getnum = 0
> 
>    qq_user=qq(476705269,'python')
>    reactor.listenUDP(0, qqClientProtocol(qq_user))
>    start = clock()
>    reactor.run()
>    "测试数据:%10d 条" %nownum
>    print "收到 %d 条" %getnum
>    print "最后收到uid为:%s" %lastuid
>    print "用时:%.2f 秒" %(clock()-start)
>    print "每秒:%f条" %(nownum / (clock()-start))
> 
> if __name__ == "__main__":
>    main()
> 
> 
> 
> 在 05-7-26,梅劲松<stephen.cn at gmail.com> 写道:
> > twisted中的udp客户端,如何在reactor中连接另外一个ip地址,或者断开连接呢?
> > 比如我连接了1.1.1.1的4000端口,但是我这个时候需要端开连接,并连接到2.2.2.2的5000端口,应该怎么做呢?
> >
> >
> > --
> > 梅劲松
> >
> 
> 
> --
> 梅劲松
> 


-- 
梅劲松

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

如下红色区域有误,请重新填写。

    你的回复:

    请 登录 后回复。还没有在Zeuux哲思注册吗?现在 注册 !

    Zeuux © 2025

    京ICP备05028076号