(转)[Python 网络编程] makefile (三)
socket.makefile(mode ='r',buffering = None,*,encoding = None,errors = None,newline = None )
返回一个与套接字相关联的文件对象。返回的确切类型取决于给makefile()提供的参数。
这些参数的解释方式与内置open()函数的解释方式相同,除了makefile方法唯一支持的mode值是'r'(默认)'w'和'b'。
套接字必须处于阻塞模式; 它可能有超时,但是如果超时发生,文件对象的内部缓冲区可能会以不一致的状态结束。
关闭返回的文件对象makefile()将不会关闭原始套接字,除非所有其他文件对象已关闭并且 socket.close()已在套接字对象上调用。
makefie的简单用法:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | #makefileimportthreading,logging,socketDATEFMT="%H:%M:%S"FORMAT="[%(asctime)s]\t [%(threadName)s,%(thread)d] %(message)s"logging.basicConfig(level=logging.INFO,format=FORMAT,datefmt=DATEFMT)sock =socket.socket()addr =('127.0.0.1',9999)event =threading.Event()sock.bind(addr)sock.listen()def_accept(sock:socket.socket):    s,addrinfo =sock.accept()    f =s.makefile(mode='rw')    whileTrue:        line =f.readline() # read(10) 文本使用readline        logging.info(line)        ifline.strip() =='quit':            break        msg ="Your msg = {}. ack".format(line)        f.write(msg)        f.flush()    f.close()    sock.close()threading.Thread(target=_accept,args=(sock,)).start()whilenotevent.wait(2):    logging.info(sock)#运行结果:[19:09:47]   [MainThread,3544] <socket.socket fd=288, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999)>[19:09:49]   [MainThread,3544] <socket.socket fd=288, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999)>[19:09:49]   [Thread-1,6044] hi?[19:09:51]   [MainThread,3544] <socket.socket fd=288, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999)>[19:09:53]   [MainThread,3544] <socket.socket fd=288, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999)>[19:09:55]   [MainThread,3544] <socket.socket fd=288, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999)>[19:09:57]   [MainThread,3544] <socket.socket fd=288, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999)>[19:09:59]   [MainThread,3544] <socket.socket fd=288, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999)>[19:10:01]   [MainThread,3544] <socket.socket fd=288, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999)>[19:10:03]   [MainThread,3544] <socket.socket fd=288, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999)>[19:10:05]   [MainThread,3544] <socket.socket fd=288, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999)>[19:10:07]   [Thread-1,6044] Are you ok?[19:10:07]   [MainThread,3544] <socket.socket fd=288, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999)>[19:10:09]   [MainThread,3544] <socket.socket fd=288, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999)>[19:10:11]   [MainThread,3544] <socket.socket fd=288, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999)>[19:10:13]   [MainThread,3544] <socket.socket fd=288, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999)>[19:10:13]   [Thread-1,6044] quit[19:10:15]   [MainThread,3544] <socket.socket [closed] fd=-1, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0> | 
TCP Server 改装成makefile:
连接两个客户端分别测试消息是否分发正常,客户端quit指令是否可以正常关闭socket,self.clients字典是否已经移除失联的socket。
客户端分别测试正常退出:quit退出,和异常退出:强制退出。然后观察服务端是否运行正常。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | #TCP Server 改装成makefileimportthreading,logging,time,random,datetime,socketDATEFMT="%H:%M:%S"FORMAT="[%(asctime)s]\t [%(threadName)s,%(thread)d] %(message)s"logging.basicConfig(level=logging.INFO,format=FORMAT,datefmt=DATEFMT)classChatServer:    def__init__(self,ip='127.0.0.1',port=9999): #启动服务        self.addr =(ip,port)        self.sock =socket.socket()        self.event =threading.Event()        self.clients ={} #客户端    defshow_client(self):        whilenotself.event.is_set():            iflen(self.clients) > 0:                logging.info(self.clients)                self.event.wait(3)    defstart(self):        self.sock.bind(self.addr)        self.sock.listen()        # accept会阻塞主线程,所以开一个新线程        threading.Thread(target=self._accept,name='accept',daemon=True).start()        threading.Thread(target=self.show_client,name='show_client',daemon=True).start()    defstop(self):        forc inself.clients.values():            c.close()        self.sock.close()        self.event.wait(3)        self.event.set()    def_accept(self):        whilenotself.event.is_set(): #多人连接            conn,client =self.sock.accept()  #阻塞            f =conn.makefile(mode='rw',encoding='utf8')            self.clients[client] =f            logging.info("{}-{}".format(conn,client))            # recv 默认阻塞,每一个连接单独起一个recv线程准备接收数据            threading.Thread(target=self._recv, args=(f, client), name='recv',daemon=True).start()    def_recv(self, f, client): #接收客户端数据        whilenotself.event.is_set():            try:                data =f.readline()            exceptException:                data ='quit'            finally:                msg =data.strip()                # Client通知退出机制                ifmsg =='quit':                    f.close()                    self.clients.pop(client)                    logging.info('{} quit'.format(client))                    break            msg ="{:%Y/%m/%d %H:%M:%S} {}:{}\n{}\n".format(datetime.datetime.now(),*client,data)            print(msg)            logging.info(msg)            forc inself.clients.values():                c.writelines(msg)                c.flush()cs =ChatServer()print('!!!!!!!!!!!')cs.start()print('~~~~~~~~~~~~~~~~~~~~')e =threading.Event()defshowthreads(e:threading.Event):    whilenote.wait(3):        logging.info(threading.enumerate())threading.Thread(target=showthreads,name='showthreads',args=(e,)).start()whilenote.wait(1): # Sever控制台退出方式    cmd =input('>>> ').strip()    ifcmd =='quit':        cs.stop()        e.wait(3)        break#运行结果:!!!!!!!!!!!~~~~~~~~~~~~~~~~~~~~>>> [15:18:49]  [show_client,4284] {('127.0.0.1', 3507): <_io.TextIOWrapper mode='rw'encoding='utf8'>}[15:18:49]   [accept,2820] <socket.socket fd=388, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 3507)>-('127.0.0.1', 3507)[15:18:49]   [showthreads,8384] [<Thread(showthreads, started 8384)>, <Thread(accept, started daemon 2820)>, <Thread(show_client, started daemon 4284)>, <_MainThread(MainThread, started 932)>, <Thread(recv, started daemon 10156)>][15:18:52]   [show_client,4284] {('127.0.0.1', 3507): <_io.TextIOWrapper mode='rw'encoding='utf8'>}[15:18:52]   [showthreads,8384] [<Thread(showthreads, started 8384)>, <Thread(accept, started daemon 2820)>, <Thread(show_client, started daemon 4284)>, <_MainThread(MainThread, started 932)>, <Thread(recv, started daemon 10156)>][15:18:54]   [recv,10156] 2017/12/2415:18:54127.0.0.1:35072017/12/2415:18:54127.0.0.1:3507123123[15:18:55]   [show_client,4284] {('127.0.0.1', 3507): <_io.TextIOWrapper mode='rw'encoding='utf8'>}[15:18:55]   [showthreads,8384] [<Thread(showthreads, started 8384)>, <Thread(accept, started daemon 2820)>, <Thread(show_client, started daemon 4284)>, <_MainThread(MainThread, started 932)>, <Thread(recv, started daemon 10156)>][15:18:58]   [show_client,4284] {('127.0.0.1', 3507): <_io.TextIOWrapper mode='rw'encoding='utf8'>}[15:18:58]   [showthreads,8384] [<Thread(showthreads, started 8384)>, <Thread(accept, started daemon 2820)>, <Thread(show_client, started daemon 4284)>, <_MainThread(MainThread, started 932)>, <Thread(recv, started daemon 10156)>][15:19:01]   [show_client,4284] {('127.0.0.1', 3507): <_io.TextIOWrapper mode='rw'encoding='utf8'>}[15:19:01]   [showthreads,8384] [<Thread(showthreads, started 8384)>, <Thread(accept, started daemon 2820)>, <Thread(show_client, started daemon 4284)>, <_MainThread(MainThread, started 932)>, <Thread(recv, started daemon 10156)>][15:19:04]   [show_client,4284] {('127.0.0.1', 3507): <_io.TextIOWrapper mode='rw'encoding='utf8'>}[15:19:04]   [showthreads,8384] [<Thread(showthreads, started 8384)>, <Thread(accept, started daemon 2820)>, <Thread(show_client, started daemon 4284)>, <_MainThread(MainThread, started 932)>, <Thread(recv, started daemon 10156)>][15:19:07]   [show_client,4284] {('127.0.0.1', 3507): <_io.TextIOWrapper mode='rw'encoding='utf8'>}[15:19:07]   [showthreads,8384] [<Thread(showthreads, started 8384)>, <Thread(accept, started daemon 2820)>, <Thread(show_client, started daemon 4284)>, <_MainThread(MainThread, started 932)>, <Thread(recv, started daemon 10156)>][15:19:10]   [show_client,4284] {('127.0.0.1', 3507): <_io.TextIOWrapper mode='rw'encoding='utf8'>}[15:19:10]   [showthreads,8384] [<Thread(showthreads, started 8384)>, <Thread(accept, started daemon 2820)>, <Thread(show_client, started daemon 4284)>, <_MainThread(MainThread, started 932)>, <Thread(recv, started daemon 10156)>][15:19:12]   [recv,10156] 2017/12/2415:19:12127.0.0.1:3507[15:19:12]   [recv,10156] ('127.0.0.1', 3507) quit2017/12/2415:19:12127.0.0.1:3507[15:19:13]   [showthreads,8384] [<Thread(showthreads, started 8384)>, <Thread(accept, started daemon 2820)>, <Thread(show_client, started daemon 4284)>, <_MainThread(MainThread, started 932)>] | 
总结:
使用makefile返回一个套接字相关联的文件对象,对该文件对象的操作方法,与普通文件操作方法一致,read,readline,write,writeline
makefile不仅仅可以对accept建立连接后的socketObject使用,也可对主线程的sock和任何socketObject使用。
(转)[Python 网络编程] makefile (三)的更多相关文章
- [Python 网络编程] makefile (三)
		socket.makefile(mode ='r',buffering = None,*,encoding = None,errors = None,newline = None )返回一个与套接字相 ... 
- python网络编程【三】(网络服务器)
		建立一个服务器需要以下4步: 1.建立socket对象. 2.设置socket选项(可选的) 3.绑定到一个端口(同样,也可以是一个指定的网卡). 4.侦听连接. 下面代码片段可以实现这些功能: ho ... 
- python 网络编程(三)---TCP 服务器端客户端实现
		客户端 客户端主要有4个步骤: 1)创建一个socket以连接服务器. socket = socket.socket(family, type),family参数代表地址家族,可为AF_INET(包括 ... 
- python 网络编程第三版
		为服务端增加多线程解决方案 1.服务端代码如下: ***这个版本并没有真正的起到多线程的作用,主要原因在于t.join():以后的版本会改进这个问题*** #!/usr/bin/python #!co ... 
- 第十一章:Python の 网络编程基础(三)
		本課主題 多线程的创建和使用 消息队列的介绍 Python 操作 memached 和 redis 实战 本周作业 消息队列的介绍 对列是在内存中创建的,如果整个进程里的程序运行完毕之后会被清空,消息 ... 
- python网络编程(三)
		udp网络通信过程 udp应用:echo服务器 参考代码 #coding=utf-8 from socket import * #1. 创建套接字 udpSocket = socket(AF_INET ... 
- 28、Python网络编程
		一.基于TCP协议的socket套接字编程 1.套接字工作流程 先从服务器端说起.服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客 ... 
- 图解Python网络编程
		返回目录 本篇索引 (1)基本原理 (2)socket模块 (3)select模块 (4)asyncore模块 (5)asynchat模块 (6)socketserver模块 (1)基本原理 本篇指的 ... 
- Python 网络编程(二)
		Python 网络编程 上一篇博客介绍了socket的基本概念以及实现了简单的TCP和UDP的客户端.服务器程序,本篇博客主要对socket编程进行更深入的讲解 一.简化版ssh实现 这是一个极其简单 ... 
随机推荐
- css3 --linear-gradient-渐变色
			//由上至下变色 background:-moz-linear-gradient( top,#f9b347,#f4ad40,#f9b347); background:-webkit-gradient ... 
- 分离式lnmp部署
			分离式lnmp简介 lnmp和lamp一样,是一种常用的web环境, 在实际环境中,lnmp中的三个服务常常为了更好的性能而分在三台主机上安装. 本篇内只介绍nginx和php-fpm+mysql分离 ... 
- elasticdump 方法迁移数据
			elasticdump -rm -ti taskrabbit/elasticsearch-dump --ignore-errors=true --offset=1000 --input=http:/ ... 
- Codeforces Round #538 (Div. 2) CTrailing Loves (or L'oeufs?)
			这题明白的意思就是求n!在b进制下的后缀零的个数. 即最大的n!%(b^k)==0的k的值.我们需要将如果要构成b这个数,肯定是由一个个质因子相乘得到的.我们只需要求出b的质因子,然后分析n!中可以组 ... 
- Js2WordCloud 词云用法
			1.引入 npm 安装: npm install js2wordcloud --save 通过script引入: <script src="dist/js2wordcloud.min. ... 
- P3398 仓鼠找sugar (一道LCA的裸题)
			https://www.luogu.org/problemnew/show/P3398 题意简单概括一下就是求树上两条路径是否相交; 有这样一个性质: if相交,则必有lca(a,b) 在路径c &l ... 
- qt字符数组转ASCII(十六进制)
			接收网络传输数据 QByteArray array;//显示字符串 QString str = QString::fromLocal8Bit(array); m_receiveTxt.append( ... 
- css 文本超出2行就隐藏并且显示省略号
			overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-box-orient: vertical; -webk ... 
- Unicode vs. UTF-8 etc.
			目测是个老问题了.随便一搜,网上各种总结过.这里不辞啰嗦,尽量简洁的备忘一下. 几个链接,有道云笔记链接,都是知乎上几个问题的摘录:阮一峰的日志,1-5 还是值得参考,但是之后的部分则混淆了 Wind ... 
- TYVJ1424-占卜DIY
			题目有点长,对于样例最好拿张A4纸模拟写一遍. 可以发现程序一定不会死循环,因为每种牌都是4张,而死循环的条件是某种牌有5张然后你拿了又放进去.如果写出来死循环了,那就是写不对了. 有几点可能是需要注 ... 
