zoukankan      html  css  js  c++  java
  • multi_socket

    threading_test.py

    #threading
    #为什么在命令行可以执行,F5不能执行
    #线程处理能导致同步问题
    from socketserver import TCPServer,ThreadingMixIn,StreamRequestHandler
    class Server(ThreadingMixIn,TCPServer):pass
    class Handler(StreamRequestHandler):
        def handle(self):
            addr=self.request.getpeername()
            print('from',addr)
            self.wfile.write(b'thanks')
            print(self.rfile.read(1024).decode())
    server=Server(('',1234),Handler)
    server.serve_forever()

    forking_test.py

    #forking 分叉
    ##Windows 不支持分叉!!
    ''''分叉占据资源,并且如果有太多的客户端时分叉不能很好分叉(尽管如此,
    对于合理数量的客户端,分叉在现代的UNIX或Linux系统中是很高效的,如果有一个多CPU系统那效率更高
    )'''
    from socketserver import TCPServer,ForkingMixIn,StreamRequestHandler
    class Server(ForkingMixIn,TCPServer):pass
    class Handler(StreamRequestHandler):
        def handle(self):
            addr=self.request.getpeername()
            print('from',addr)
            self.wfile.write(b'thanks')
    server=Server(('',1234),Handler)
    server.serve_forever()

    select_test.py

    #asynchronous I/O
    '''
    只处理在给定时间内真正要进行通信的客户端。不需要一直监听,只要监听(或读取)一会儿,
    然后把它放到其他客户端的后面
    这是asyncore/asynchat框架和Twisted框架采用的方法,这种功能的基础是select函数,
    如果poll函数可用,那也可以是它,这两个函数都来自select模块。
    这两个函数中,poll的伸缩性更好,但它只能在UNIX系统中使用
    
    select需要3个序列作为它的必选参数,此外还有一个可选的以秒为单位的超时时间作为第4个参数
    这些序列是文件描述符整数(或是带有返回这样整数的fileno方法的对象)。这些就是我们等待的连接
    3个序列用于输入,输出和异常情况(错误和类似的东西)
    如果没有给定超时时间,select会阻塞(也就是处于等待状态),直到其中一个文件描述符已经为
    行动做好了准备;如果给定了超时时间,select最多阻塞给定的超时时间,如果给定的超时时间是0,
    那么就给出一个连续的poll(即不阻塞)。select的返回值是3个序列(也就是一个长度为3的元组),
    没个代表相应参数的一个活动子集。比如,返回的第一个序列是一个输入文件描述符的序列,其中
    有一些可以读取的东西
    '''
    import socket,select
    s=socket.socket()
    host=socket.gethostname()
    port=1234
    s.bind((host,port))
    s.listen(5)
    inputs=[s]
    while True:
        rs,ws,es=select.select(inputs,[],[])
        for r in rs:
            if r is s:
                c,addr=s.accept()
                print('from',addr)
                inputs.append(c)
                #c.send(b'thank')
                for w in ws:
                    if w:
                        w.send(b'thanks')
            else:
                try:
                    data=r.recv(1024)
                    disconnect=not data
                except socket.error:
                    disconnect=True
    
                if disconnect:
                    print(r.getpeername(),'disconnect')
                    inputs.remove(r)
                else:
                    print(data.decode())

    poll_test.py

    #poll_test
    '''
    在调用poll时,会得到一个poll对象。然后就可以使用poll对象的register方法注册一个文件描述符(
    或使用带有fileno方法的对象)。注册后可以unregister方法移除注册的对象
    注册了一些对象(比如套接字)以后,就可以调用poll方法(带有一个可选的超时时间参数)并
    得到一个(fd,event)格式列表(可能是空的),其中fd是文件描述符,event告诉你发生了什么。
    这是一个位掩码,意思是它是一个整数,这个整数的每个位对应不同的事件。
    那些不同的事件是select模块的常量。为了验证是否设置了一个给定位(也就是说,一个给定的事件
    是否发生了),可以使用按位与操作符:
    if event & select.POLLIN:...
    '''
    import socket,select
    s=socket.socket()
    host=socket.gethostname()
    port=1234
    s.bind((host,port))
    
    fdmap={s.fileno():s}
    
    s.listen(5)
    p=select.poll()
    p.register(s)
    while True:
        events=p.poll()
        for fd,event in events:
            if fd=s.fileno():
                c,addr=s.accept()
                print('from',addr)
                p.register(c)
                fdmap[c.fileno]=c
            elif event & select.POLLIN:
                data=fdmap[fd].recv(1024)
                if not data:
                    print(fdmap[fd].getpeername(),'disconnect')
                    p.unregister(fd)
                    del fdmap[fd]
            else:
                print(data)

    twisted_test.py

    #twisted
    '''
    之前编写的基本套接字服务器是显示的。其中的一些有很清楚的事件循环,来查找新的连接和新数据,
    而基于socketserver的服务器有一个隐式循环,在循环中服务器查找连接并为每个连接创建一个处理程序,
    但处理程序在要读数据时必须是显式的
    Twisted使用一个事件甚至多个基于事件的方法。要编写基本的服务器,就要实现处理比如
    新客户连接,新数据到达以及一个客户端断开连接等事件的事件处理程序
    
    事件处理程序在一个协议(protocol)中定义,在一个新的连接到达时,同样需要一个创建这种协议对象
    的工厂(factory),但如果只是想要创建一个通用的协议类的实例,那么就可以使用twisted自带的工厂
    当编写自己的协议时,要使用和超类一样的模块中的protocol。得到了一个连接后,时间处理程序connectionMade
    就会被调用。丢失了一个连接后,connectionLost就会被调用。来自客户端的数据是通过处理程序
    dataReceived接收的。当然不能使用事件处理策略来把数据发回到客户端,如果要实现此功能,可以
    使用对象self.transport的write方法,也有一个包含客户机地址的client属性
    '''
    from twisted.internet import reactor
    from twisted.internet.protocol import Protocol,Factory
    class SimpleLogger(Protocol):
        def connectionMade(self):
            print('from',self.transport.client)
            self.transport.write(b'thanks')
        def connectionLost(self,reason):
            print(self.transport.client,'disconnected')
        def dataReceived(self,data):
            print(data.decode())
    factory=Factory()
    factory.protocol=SimpleLogger
    reactor.listenTCP(1234,factory)
    reactor.run()

    twisted_LineReceiver.py

    #twisted LineReceiver协议
    from twisted.internet import reactor
    from twisted.internet.protocol import Factory
    from twisted.protocols.basic import LineReceiver
    class SimpleLogger(LineReceiver):
        def connectionMade(self):
            print('from',self.transport.client)
            #self.transport.write(b'thanks')
            self.sendLine(b'thanks2')
        def connectionLost(self,reason):
            print(self.transport.client,'disconnected')
        def lineReceived(self,line):
            #客户端发送的数据要加
    
            print(line.decode())
    factory=Factory()
    factory.protocol=SimpleLogger
    reactor.listenTCP(1234,factory)
    reactor.run()
  • 相关阅读:
    centos7 安装mysql
    ketlle windows下的安装(最基本)
    Spark参数详解 一(Spark1.6)
    SSM项目集成Lucene+IKAnalyzer在Junit单元测试中执行异常
    解决jquery.pjax加载后的异常滚动
    码云项目克隆至github
    JFinal获取多个model
    避免layui form表单重复触发submit绑定事件
    解决pjax重复绑定
    jfinal 拦截器中判断是否为pjax请求
  • 原文地址:https://www.cnblogs.com/feifeidxl/p/5617920.html
Copyright © 2011-2022 走看看