日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > python >内容正文

python

[python3.3]Python异步Socket编程【TCP】

發(fā)布時(shí)間:2023/12/9 python 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [python3.3]Python异步Socket编程【TCP】 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

參考:?http://www.cnblogs.com/snailrun/p/3805188.html

異步網(wǎng)絡(luò)據(jù)說(shuō)能極大的提高網(wǎng)絡(luò)server的連接速度,所以打算寫(xiě)一個(gè)專(zhuān)題,來(lái)學(xué)習(xí)和了解異步網(wǎng)絡(luò).因?yàn)镻ython有個(gè)非常出名的異步Lib:Twisted,所以就用Python來(lái)完成.?

OK,首先寫(xiě)一個(gè)pythone socket的server段,對(duì)開(kāi)放三個(gè)端口:10000,10001,10002.krondo的例子中是每個(gè)server綁定一個(gè)端口,測(cè)試的時(shí)候需要分別開(kāi)3個(gè)shell,分別運(yùn)行.這太麻煩了,就分別用三個(gè)Thread來(lái)運(yùn)行這些services.?

import optparse import os import socket import time from threading import Thread from io import StringIOtxt = '''1111 2222 3333 4444 '''# 服務(wù)端程序處理過(guò)程 def server(listen_socket):while True:buf = StringIO(txt)sock, addr = listen_socket.accept()print('Somebody at %s wants poetry!' %(addr,))while True:try:line = buf.readline().strip()if not line:sock.close()breaksock.sendall(line.encode('utf8')) # this is a blocking callprint('send bytes to client: %s' %line)except socket.error:sock.close()breaktime.sleep(0.5) # server每發(fā)送一個(gè)單詞后等待一會(huì)sock.close()print('\n')# 同時(shí)開(kāi)啟三個(gè)服務(wù)端線程,分別在三個(gè)端口監(jiān)聽(tīng) # 服務(wù)端程序?yàn)樽枞绞?#xff0c;只能一次服務(wù)于一個(gè)客戶端 def main():ports = [10000, 10001, 10002]for port in ports:listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)addres = ('127.0.0.1', port)listen_socket.bind(addres)listen_socket.listen(5)print("start listen at: %d" %port)worker = Thread(target = server, args = [listen_socket])worker.setDaemon(True)worker.start()if __name__ == '__main__':main()while True:time.sleep(0.1) # 如果不sleep的話, CPU會(huì)被Python完全占用了
下面是一個(gè)client, 用阻塞方式,先后連接這個(gè)三個(gè)端口的server:?

from socket import *# 建立三個(gè)客戶端,分別連接三個(gè)不同的服務(wù)端程序, 接收服務(wù)端傳過(guò)來(lái)的數(shù)據(jù)并打印 # 這三個(gè)客戶端是阻塞方式通信的 if __name__ == '__main__':ports = [10000, 10001, 10002]for port in ports:address = ('127.0.0.1', port)sock = socket(AF_INET, SOCK_STREAM)sock.connect(address)poem = ''while True:data = sock.recv(4)if not data:sock.close()breakpoem += data.decode('utf8')print(poem)sock.close()

下面用異步的client來(lái)讀取,代碼如下:

import datetime, errno, optparse, select, socketdef connect(port):"""Connect to the given server and return a non-blocking socket."""address = ('127.0.0.1', port)sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)sock.connect(address)sock.setblocking(0) # 設(shè)置為非阻塞模式return sockdef format_address(address):host, port = addressreturn '%s:%s' % (host or '127.0.0.1', port)if __name__ == '__main__':ports = [10000, 10001, 10002]start = datetime.datetime.now()sockets = list(map(connect, ports))poems = dict.fromkeys(sockets, '') # socket -> accumulated poemsock2task = dict([(s, i + 1) for i, s in enumerate(sockets)])while sockets:#運(yùn)用select來(lái)確保那些可讀取的異步socket可以立即開(kāi)始讀取IO#OS不停的搜索目前可以read的socket,有的話就返回rlistrlist, _, _ = select.select(sockets, [], [])for sock in rlist:data = ''while True:try:new_data = sock.recv(1024)new_data = new_data.decode('utf8')except socket.error as e:if e.args[0] == errno.EWOULDBLOCK:breakraiseelse:if not new_data:breakelse:print(new_data)data += new_datatask_num = sock2task[sock]if not data:print(poems[sock]) # 打印sock接收到的數(shù)據(jù)sockets.remove(sock)sock.close()print('Task %d finished\n' % task_num)else:addr_fmt = format_address(sock.getpeername())msg = 'Task %d: got %d bytes of poetry from %s\n'print(msg % (task_num, len(data), addr_fmt))poems[sock] += data # 保存每個(gè)sock接收到的數(shù)據(jù)elapsed = datetime.datetime.now() - startprint('Got poems in %s' %elapsed)
結(jié)果只需要2秒就完成了讀取任務(wù)。效率非常明顯啊。對(duì)客戶端的異步改造主要有兩點(diǎn):?


    • 同步模式下,客戶端分別創(chuàng)建socket;而在異步模式下,client開(kāi)始就創(chuàng)建了所有的socket。
    • 通過(guò)“sock.setblocking(0)”設(shè)置socket為異步模式。
    • 通過(guò)Unix系統(tǒng)的select來(lái)返回可讀取socket信息
    • 最為核心的是8行和26行。尤其是26行的select操作返回待讀取socket的列表。


總結(jié)

以上是生活随笔為你收集整理的[python3.3]Python异步Socket编程【TCP】的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。