标签:0.1 127.0 15 Python self 编程 makefile 19 client
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 |
#makefile
import threading,logging,socket
DATEFMT = "%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' )
while True :
line = f.readline() # read(10) 文本使用readline
logging.info(line)
if line.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()
while not event.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 改装成makefile
import threading,logging,time,random,datetime,socket
DATEFMT = "%H:%M:%S"
FORMAT = "[%(asctime)s]\t [%(threadName)s,%(thread)d] %(message)s"
logging.basicConfig(level = logging.INFO, format = FORMAT ,datefmt = DATEFMT)
class ChatServer:
def __init__( self ,ip = '127.0.0.1' ,port = 9999 ): #启动服务
self .addr = (ip,port)
self .sock = socket.socket()
self .event = threading.Event()
self .clients = {} #客户端
def show_client( self ):
while not self .event.is_set():
if len ( self .clients) > 0 :
logging.info( self .clients)
self .event.wait( 3 )
def start( 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()
def stop( self ):
for c in self .clients.values():
c.close()
self .sock.close()
self .event.wait( 3 )
self .event. set ()
def _accept( self ):
while not self .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): #接收客户端数据
while not self .event.is_set():
try :
data = f.readline()
except Exception:
data = 'quit'
finally :
msg = data.strip()
# Client通知退出机制
if msg = = '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)
for c in self .clients.values():
c.writelines(msg)
c.flush()
cs = ChatServer()
print ( '!!!!!!!!!!!' )
cs.start()
print ( '~~~~~~~~~~~~~~~~~~~~' )
e = threading.Event()
def showthreads(e:threading.Event):
while not e.wait( 3 ):
logging.info(threading. enumerate ())
threading.Thread(target = showthreads,name = 'showthreads' ,args = (e,)).start()
while not e.wait( 1 ): # Sever控制台退出方式
cmd = input ( '>>> ' ).strip()
if cmd = = '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 / 24 15 : 18 : 54 127.0 . 0.1 : 3507
2017 / 12 / 24 15 : 18 : 54 127.0 . 0.1 : 3507
123
123
[ 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 / 24 15 : 19 : 12 127.0 . 0.1 : 3507
[ 15 : 19 : 12 ] [recv, 10156 ] ( '127.0.0.1' , 3507 ) quit
2017 / 12 / 24 15 : 19 : 12 127.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使用。
标签:0.1,127.0,15,Python,self,编程,makefile,19,client 来源: https://www.cnblogs.com/liujiacai/p/10504111.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。