温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

socket的epoll模型怎么使用

发布时间:2021-12-18 14:47:03 阅读:96 作者:iii 栏目:大数据
开发者测试专用服务器限时活动,0元免费领,库存有限,领完即止! 点击查看>>

这篇文章主要介绍“socket的epoll模型怎么使用”,在日常操作中,相信很多人在socket的epoll模型怎么使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”socket的epoll模型怎么使用”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

select模型虽好,却有一个缺陷,只能对1024个文件描述符进行监视,虽然可以通过重新编译内核获得更大的监视数量,但这样做还不如将目光投向更高级的epoll模型。select模型中,每一次都需要遍历所有处于监视中的文件描述符,判断他们哪个可写,哪个可读,这样一来,你监视的越多,速度越慢,而在epoll模型中,所有添加到epoll中的事件都会网卡驱动程序建立起回调关系,简言之,如果有一个连接可写,那么这个可写的事件就会报告给你,而你不需要挨个询问他们哪个连接可写,哪个连接可读。

下面的示例,所实现的功能,和之前的示例一样,但更加高效:

#coding=utf-8import socketimport selectimport sysfrom MsgContainer import MsgContainerdef start_server(port):    serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)    serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)    serversocket.bind(('0.0.0.0', port))    #accept队列大小为100    serversocket.listen(100)    serversocket.setblocking(0)    epoll = select.epoll()    #注册一个in事件,等待有数据可读    epoll.register(serversocket.fileno(), select.EPOLLIN)    try:        #保存连接,请求,和响应信息        connections = {};        message_queues = {}         #存储可发送的数据        while True:            #最多等待1秒钟时间,有事件返回事件列表            events = epoll.poll(1)            for fileno, event in events:                #事件的句柄是server                if fileno == serversocket.fileno():                    connection, address = serversocket.accept()                    #设置为非阻塞的                    connection.setblocking(0)                    #新建的连接也注册读事件                    epoll.register(connection.fileno(), select.EPOLLIN)                    connections[connection.fileno()] = connection                    message_queues[connection.fileno()] = MsgContainer()                    #不是server,那就是建立的连接,现在连接可读                elif event & select.EPOLLIN:                    data = connections[fileno].recv(1024)                    if data :                        epoll.modify(fileno, select.EPOLLOUT)                        message_queues[fileno].add_data(data)                    else:                        epoll.modify(fileno, 0)                        connections[fileno].shutdown(socket.SHUT_RDWR)                        del connections[fileno]                        del message_queues[fileno]                elif event & select.EPOLLOUT:                    #可写的事件被触发                    if not fileno in message_queues or not fileno in connections:                        continue                    clientsocket = connections[fileno]                    mc = message_queues[fileno]                    msgs = mc.get_all_msg()                    for msg in msgs:                        msg = mc.pack_msg(msg)                        clientsocket.send(msg)                    mc.clear_msg()                    #需要回写的数据已经写完了,再次注册读事件                    epoll.modify(fileno, select.EPOLLIN)                elif event & select.EPOLLHUP:                    #被挂起了,注销句柄,关闭连接,这时候,是客户端主动断开了连接                    epoll.unregister(fileno)                    if fileno in connections:                        connections[fileno].close()                        del connections[fileno]                    if fileno in message_queues:                        del message_queues[fileno]    finally:        epoll.unregister(serversocket.fileno())        epoll.close()        serversocket.close()if __name__ == '__main__':    if len(sys.argv) == 2:        port = int(sys.argv[1])        start_server(port)    else:        print u'请输入端口号'

下面看client端的代码:

#coding=utf-8import sysimport timeimport datetimeimport socketimport cPickleimport threadingfrom MsgContainer import MsgContainerdef start_client(addr,port,msgCount):    mc = MsgContainer()    PLC_ADDR = addr    PLC_PORT = port    time_lst = []    s = socket.socket()    s.connect((PLC_ADDR, PLC_PORT))    seconds1 = int(time.time())    i = 0    while True:        seconds = int(time.time())        microseconds = datetime.datetime.now().microsecond        data = {'sec':seconds,'micsec':microseconds}        data = cPickle.dumps(data)        data = mc.pack_msg(data)        s.send(data)        recv_data = s.recv(1024)        mc.add_data(recv_data)        msgs = mc.get_all_msg()        seconds = int(time.time())        microseconds = datetime.datetime.now().microsecond        for msg in msgs:            msgdict = cPickle.loads(msg)            time_lst.append(((seconds-msgdict['sec'])*1000000 + microseconds-msgdict['micsec'])/1000.0)        mc.clear_msg()        i += 1        if i>msgCount:            print sum(time_lst)/float(len(time_lst))            break    s.close()if __name__ == '__main__':    if len(sys.argv) == 4:        addr = sys.argv[1]        port = int(sys.argv[2])        msgCount = int(sys.argv[3])        t_lst = []        for i in range(100):            t = threading.Thread(target=start_client,args=(addr,port,msgCount))            t_lst.append(t)        for t in t_lst:            t.start()        for t in t_lst:            t.join()    #start_client('123.56.190.151',8091,100

在客户端,每次起100个线程尝试建立连接,如果server端的accept队列大小设置的小,例如设置为10,就会出现个别连接无法建立的情况,所以我这里设置为100。

到此,关于“socket的epoll模型怎么使用”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!

亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

原文链接:https://my.oschina.net/u/4632317/blog/4538794

AI

开发者交流群×