1.Twisted框架构建简单的C/Sreact
要写一个基于twisted框架的服务器,你要实现事件处理器,它处理诸如一个新的客户端链接、新的数据到达和客户端链接中断等状况。浏览器
在Twisted中,你的事件处理器定义在一个protocol中;你也须要一个factory, 当一个新的链接到达时它可以构造这个protocol对象,可是若是你仅仅想建立一个自定义的Protocol类的实例的话,你可使用来自 Twisted的factory,Factory类在模块twisted.internet.protocol中。当你写你的protocol时,使用twisted.internet.protocol模块中的Protocol做为你的父类。服务器
当你获得一个链接时,事件处理器connectionMade被调用;架构
当你丢失一个链接时,connectionLost被调用;app
从客户端接受数据使用处理器dataReceived;框架
可是你不能使用事件处理策略向客户端发送数据;要向客户端发送数据,你能够使用self.transport,它有一个write方法。它也有一个client属性,其中包含了客户端的地址(主机名和端口),即self.transport.client。socket
Eg:函数
twisted server:测试
[cpp]
ui
from twisted.internet import reactor
from twisted.internet.protocol import Protocol, Factory
# 定义你Protocol类
class SimpleLogger(Protocol):
def connectionMade(self):
print 'Got connection from', self.transport.client #self.transport.client =客户端主机名和端口
def connectionLost(self, reason):
print self.transport.client, 'disconnected'
def dataReceived(self, data):
print data
# 实例化Factory
factory = Factory()
# 设置factory的protocol属性以便它知道使用哪一个protocol与客户端通讯(这就是所谓的你的自定义
# protocol)
factory.protocol = SimpleLogger
# 监听指定的端口
reactor.listenTCP(1234, factory)
# 开始运行主程序
reactor.run()
测试的cilent端:
[cpp]
#socket client end
from socket import *
s=socket(AF_INET,SOCK_STREAM)
remote_host=gethostname()
print 'remote_ip:',remote_host
port=1234
s.connect((remote_host,port)) #发起链接
'''
socket对象的getpeername()和getsockname()方法都返回包含一个IP地址和端口的二元组
(这个二元组的形式就像你传递给connect和bind的)。
getpeername返回所链接的远程socket的地址和端口,getsockname返回关于本地socket的相同信息。
'''
print("Connected from",s.getsockname()) ##返回本地IP和端口
print("Connected to",s.getpeername()) ##返回服务端IP和端口
s.send('i am form client')
#print 'what i got from select server is:'
#print s.recv(1024)
'''
send,sendto,recv和recvfrom方法都有一个可选的参数flags,默认值为0。
你能够经过对socket.MSG_*变量进行组合(按位或)来创建flags的值。
这些值因平台而有所不一样,可是最通用的值以下所示:
MSG_OOB:处理带外数据(既TCP紧急数据)。
MSG_DONTROUTE:不使用路由表;直接发送到接口。
MSG_PEEK:返回等待的数据且不把它们从队列中删除。
'''
运行结果:
server端:
[cpp]
>>> ================================ RESTART ================================
>>>
Got connection from ('172.22.144.167', 5466)
i am form client
client 端:
[cpp]
>>> ================================ RESTART ================================
>>>
remote_ip: PC-200910021344
('Connected from', ('172.22.144.167', 5466))
('Connected to', ('172.22.144.167', 1234))
>>>
2.自定义Protocol--利用LineReceiver类做为父类
模块twisted.protocols.basic中包含了几个有用的已存在的protocol,其中的LineReceiver执行dataReceived并在接受到了一个完整的行时调用事件处理器lineReceived。若是当你在接受数据时除了使用lineReceived,还要作些别的,那么你可使用LineReceiver定义的名为rawDataReceived事件处理器。
Eg:
Server端:
[cpp]
from twisted.internet import reactor
from twisted.internet.protocol import Factory
from twisted.protocols.basic import LineReceiver
class SimpleLogger(LineReceiver):
def connectionMade(self):
print 'Got connection from', self.transport.client
def connectionLost(self, reason):
print self.transport.client, 'disconnected'
#注意必须接收到完整的行(即遇到\r\n结束标志)时该函数才能成功执行
def lineReceived(self, line):
print line
length=len(line)
responsemsg='Dear cilent,I have received '+str(length)+' bytes from you\r\n'
self.transport.write(responsemsg)#向客户端发送数据
factory = Factory()
factory.protocol = SimpleLogger
reactor.listenTCP(1234, factory)
reactor.run()
Client端:
[cpp]
#socket client end
from socket import *
s=socket(AF_INET,SOCK_STREAM)
remote_host=gethostname()
print 'remote_host:',remote_host
port=1234
s.connect((remote_host,port)) #发起链接
print("Connected from",s.getsockname()) ##返回本地IP和端口
print("Connected to",s.getpeername()) ##返回服务端IP和端口
s.send('i am form client\r\n')#发送一行字符串(以\r\n 结束)到服务器端
s.send('next message\r\n')
print 'the msg i got from select server is:'
print s.recv(1024)
运行结果:
Server端:
[cpp]
>>> ================================ RESTART ================================
>>>
Got connection from ('172.22.144.167', 9668)
i am form client
next message
Client端:
[cpp]
>>> ================================ RESTART ================================
>>>
remote_host: PC-200910021344
('Connected from', ('172.22.144.167', 9668))
('Connected to', ('172.22.144.167', 1234))
the msg i got from select server is:
Dear cilent,I have received 16 bytes from you
Dear cilent,I have received 12 bytes from you
>>>
3.使用twisted框架建立Web服务器
Web Server 端:
[cpp]
#Main Point:Build Web Server
from twisted.internet import protocol,reactor
from twisted.protocols import basic
class SimpleLogger(basic.LineReceiver):
def connectionMade(self):
print 'Got connection from', self.transport.client
def connectionLost(self, reason):
print self.transport.client, 'disconnected'
def lineReceived(self,line):
print 'data from client are as followings:'
print line
responseData="Welcome to Twisted World!\r\n"
self.transport.write(responseData)
self.transport.loseConnection() #终止链接
# 实例化protocol.ServerFactory()
'''
protocolp.py
class ServerFactory(Factory):
"""Subclass this to indicate that your protocol.Factory is only usable for servers.
"""
'''
factory = protocol.ServerFactory()# ***0120 protocol.ServerFactory()
factory.protocol = SimpleLogger
reactor.listenTCP(6688, factory)
reactor.run()
浏览器客户端测试结果:
Server端运行结果:
[cpp] view plaincopy
>>> ================================ RESTART ================================
>>>
Got connection from ('172.22.144.167', 10293)
Got connection from ('172.22.144.167', 10294)
Got connection from ('172.22.144.167', 10297)
data from client are as followings:
GET / HTTP/1.1
('172.22.144.167', 10297) disconnected
Got connection from ('172.22.144.167', 10298)
data from client are as followings:
GET /favicon.ico HTTP/1.1
('172.22.144.167', 10298) disconnected
('172.22.144.167', 10293) disconnected
('172.22.144.167', 10294) disconnected
4. http请求和响应报文
功能:
返回客户端的请求信息(http请求报文)
Web Server端代码:
[cpp] view plaincopy
from twisted.protocols import basic
from twisted.internet import protocol,reactor
class HttpEchoProtocol(basic.LineReceiver):
def __init__(self):
self.lines=[]
self.gotRequest=False
def lineReceived(self,line):
self.lines.append(line)
if not line and not self.gotRequest:
#0121
print 'the msg browser client send to me(http request head) is:'
for e in self.lines:
print e
#
self.sendResponse()
self.gotRequest=True
def sendResponse(self):
#0121 "\r\n".join(self.lines) 列表中的每一条请求消息字符串均用\r\n链接起来
responseBody="Dear Client,the msg you sent to me are as followings:\r\n\r\n"+"\r\n".join(self.lines)
#send msg to the browser client 0121
#http response head 0121
self.sendLine("HTTP/1.0 200 OK") #请求成功 0121 (必须) senfLine自动在消息字符串末尾添加\r\n
self.sendLine("Content-Type: text/plain")
self.sendLine("Content-Length: %i"%len(responseBody))
#下面两行语句[1][2]等价 #0121
#self.sendLine("") #http头结束标志 (必须) \r\n [1]
self.transport.write("\r\n") #[2]
self.transport.write(responseBody) #向客户端发送数据
self.transport.loseConnection() #终止链接
f=protocol.ServerFactory()
f.protocol=HttpEchoProtocol
reactor.listenTCP(5000,f)
reactor.run()
浏览器测试结果:
服务器端运行结果: