复习:消息队列
为了防止消息丢失,或者是调用方,不需一直等待响应方的结果。
# threadtest.py
<code>import</code> <code>codecs</code>
<code>from</code> <code>queue </code><code>import</code> <code>Queue</code>
<code>from</code> <code>threading </code><code>import</code> <code>Thread</code>
<code>import</code> <code>time</code>
<code>class</code> <code>Produce(Thread):</code>
<code> </code><code>def</code> <code>__init__(</code><code>self</code><code>, queue):</code>
<code> </code><code>super</code><code>(Produce, </code><code>self</code><code>).__init__()</code>
<code> </code><code>self</code><code>.fileName </code><code>=</code> <code>"../firstlession/passwd"</code>
<code> </code><code>self</code><code>.fileList </code><code>=</code> <code>list</code><code>()</code>
<code> </code><code>self</code><code>.queue </code><code>=</code> <code>queue</code>
<code> </code><code>def</code> <code>run(</code><code>self</code><code>):</code>
<code> </code><code>with codecs.</code><code>open</code><code>(</code><code>self</code><code>.fileName) as f:</code>
<code> </code><code>self</code><code>.fileList </code><code>+</code><code>=</code> <code>f.readlines()</code>
<code> </code><code>for</code> <code>line </code><code>in</code> <code>self</code><code>.fileList:</code>
<code> </code><code>self</code><code>.queue.put(line)</code>
<code>class</code> <code>Consumer(Thread):</code>
<code> </code><code>super</code><code>(Consumer, </code><code>self</code><code>).__init__()</code>
<code> </code><code>self</code><code>.newPasswd </code><code>=</code> <code>"newpasswd.txt"</code>
<code> </code><code>self</code><code>.stat </code><code>=</code> <code>1</code>
<code> </code><code>while</code> <code>1</code><code>:</code>
<code> </code><code>if</code> <code>self</code><code>.queue.empty():</code>
<code> </code><code>time.sleep(</code><code>2</code><code>)</code>
<code> </code><code>self</code><code>.stat </code><code>+</code><code>=</code> <code>1</code>
<code> </code><code>if</code> <code>self</code><code>.stat </code><code>=</code><code>=</code> <code>5</code><code>:</code>
<code> </code><code>break</code>
<code> </code><code>else</code><code>:</code>
<code> </code><code>self</code><code>.stat </code><code>=</code> <code>1</code>
<code> </code><code>data </code><code>=</code> <code>self</code><code>.queue.get()</code>
<code> </code><code>self</code><code>.fileList.append(data)</code>
<code> </code><code>with codecs.</code><code>open</code><code>(</code><code>self</code><code>.newPasswd, </code><code>'w'</code><code>) as f:</code>
<code> </code><code>f.writelines(</code><code>self</code><code>.fileList)</code>
调用
# thread1.py
<code>from</code> <code>onlive.secondlesson.threadtest </code><code>import</code> <code>Produce, Consumer</code>
<code>def</code> <code>main():</code>
<code> </code><code>q </code><code>=</code> <code>Queue()</code>
<code> </code><code>produce </code><code>=</code> <code>Produce(q)</code>
<code> </code><code>consumer </code><code>=</code> <code>Consumer(q)</code>
<code> </code><code>produce.start()</code>
<code> </code><code>consumer.start()</code>
<code>if</code> <code>__name__ </code><code>=</code><code>=</code> <code>'__main__'</code><code>:</code>
<code> </code><code>main()</code>
socket 简介
TCP的可靠性实现:
(1)校验码
(2)接收方反馈
(3)信息包附带序号
UDP:
(1)快 不需要花费时间建立和关闭连接
(2)快 偶尔丢失一两个消息包无所谓,但是TCP会严格检查
(3)快 UDP的限制是一个信息包不超过64KB的数据
TCP和UDP区别:
UDP不建立连接,只保证数据的完整性,数据传输快,但是不保证数据是否真的被收到,也不保证数据是否只接收一次,也不保证次序。
TCP则相反。
服务端是用来给一个或多个客户端提供服务的,当客户端发起请求,开始等待服务端的返回结果,服务端接受完请求以后,根据自己的逻辑处理请求,并返回给客户端,客户端接收到返回结果以后,关闭和服务端的连接。
[备注]:只要是发送数据的就是"写",只要是接收数据的就是"读"。
最常用的客户端和服务端有两种模式:C/S模式(mysql) 和 B/S模式(百度、京东、淘宝网站等)
socket流程:
(1)服务端创建完一个socket以后
(2)需要绑定一个IP:PORT
(3)对其进行监听(listen)-->【监听的方法内需要带一个数字,这个数字表示同时有多少个客户端可以来访问服务端】
(4)然后接收请求(accept)--> 【客户端每创建一个连接,调用 "connect函数" 后,服务端就需要生成一个新的socket连接和客户端进行传输,传输完成后关闭客户端连接、关闭服务端;服务端永远要比客户端多一个socket连接,如果说客户端是n个socket连接,那么服务端就要创建n+1个socket连接,因为刚开始启动服务端的时候,服务端就要创建一个socket连接,每当从客户端过来一个连接,服务端就要创建一个socket连接跟客户端进行交互,所以服务端比客户端多一个连接。】
socket常用函数讲解:
创建套接字:
s = socket.socket(address family, socket type)
address family:
socket.AF_INET 默认ipv4
socket.AF_INET6 ipv6
socket.AF_UNIX 只用于单一unix系统间进行通信
socket type:
socket.SOCK_STREAM 流式socket TCP
socket.SOCK_DGRAM 数据报式socket UDP
TCP 方式 socket:
(1)创建socket:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
(2)绑定地址:
address = ('0.0.0.0', 8009)
s.bind(address) 或者 s.bind((0.0.0.0, 8009)) 两种方式相同;
【注意:address 必须是一个元组,容易错误,address = (host, port)】
【host:服务端ip,字符串类型,如果为0.0.0.0,代表本机的任意一个IP】
【port:服务端提供的端口,整形,0-1024为系统保留(不选这里面的端口)】
(3)监听消息:
s.listen(badklog)
backlog 代表可以同时接受多少个socket连接
(4)接受连接:
conn, addr = s.accept()
接受连接并返回元组(conn,addr),其中conn是新的套接字对象,每个新的连接就创建一个新的对象。可以用来接受和发送数据,addr是客户端的地址:包含host和port。
(5)发送数据:
s.send(string) 发送字符串到连接的套接字,可能未将指定内容全部发送;
s.sendall(string) 内部递归调用send,将所有内容发送出去,建议使用。
(6)接收数据:
data = s.recv(bufsize)
接收套接字数据,数据以字符串形式返回,bufsize指定最多接收的数据量,可以使用1024, 2048
如果不知道接收的数量有多少,可以能几个字节,可能几兆,一般通过循环接收。
UDP 方式 socket:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.sendto(string)
data, address = s.recvfrom(bufsize)
客户端:
客户端首先也要创建socket套接字
客户端连接服务端函数:
s.connect(address) #连接到address的套接字
result - connect_ex(address) #成功返回0,失败返回错误码
通用:
s.close() #关闭套接字
s.getsocketname() #获取套接字的名字
s.settimeout(timeout) #设置套接字超时时间,timeout为float类型,单位秒
s.gettimeout() #获得套接字超时时间
s.setblocking(flag) #flage为bool值
setblocking(True) is equivalent to settimeout(None); #不设置超时时间,一直阻塞在那里
setblocking(False) is equivalent to settimeout(0.0); #设置超时时间为0,如果设置False,accept和recv一旦无数据,则报错。
s.fileno() # 返回套接字的文件描述符(一个小整数)。这对于select.select()是有用的。
socket例子:
写socket工具:
# util.py
<code>import</code> <code>socket</code>
<code>class</code> <code>InitSocketTest(</code><code>object</code><code>):</code>
<code> </code><code>def</code> <code>__init__(</code><code>self</code><code>, host, port, </code><code>type</code><code>):</code>
<code> </code><code>self</code><code>.host </code><code>=</code> <code>host</code>
<code> </code><code>self</code><code>.port </code><code>=</code> <code>port</code>
<code> </code><code>self</code><code>.address </code><code>=</code> <code>(host, port)</code>
<code> </code><code>self</code><code>.</code><code>type</code> <code>=</code> <code>type</code>
<code> </code><code>self</code><code>.s </code><code>=</code> <code>None</code>
<code> </code><code>self</code><code>.creatsocket()</code>
<code> </code><code>def</code> <code>creatsocket(</code><code>self</code><code>):</code>
<code> </code><code>if</code> <code>self</code><code>.</code><code>type</code><code>.upper() </code><code>=</code><code>=</code> <code>"TCP"</code><code>:</code>
<code> </code><code>self</code><code>.s </code><code>=</code> <code>socket.socket(socket.AF_INET, socket.SOCK_STREAM)</code>
<code> </code><code>elif</code> <code>self</code><code>.</code><code>type</code><code>.upper </code><code>=</code><code>=</code> <code>"UDP"</code><code>:</code>
<code> </code><code>self</code><code>.s </code><code>=</code> <code>socket.socket(socket.AF_INET, socket.SOCK_DGRAM)</code>
<code> </code><code>else</code><code>:</code>
<code> </code><code>print</code><code>(</code><code>"you must input the InitSocket(type) is 'UDP|TCP' "</code><code>)</code>
<code>class</code> <code>SocketServerTest(InitSocketTest):</code>
<code> </code><code>def</code> <code>__init__(</code><code>self</code><code>, host, port, </code><code>type</code><code>, backlog):</code>
<code> </code><code>self</code><code>.backlog </code><code>=</code> <code>backlog</code>
<code> </code><code>super</code><code>(SocketServerTest, </code><code>self</code><code>).__init__(host, port, </code><code>type</code><code>)</code>
<code> </code><code>self</code><code>.clientAddress </code><code>=</code> <code>None</code>
<code> </code><code>self</code><code>.s.bind(</code><code>self</code><code>.address)</code>
<code> </code><code>self</code><code>.s.listen(</code><code>self</code><code>.backlog)</code>
<code> </code><code>print</code><code>(</code><code>"server starting…………"</code><code>)</code>
<code> </code><code>conn, </code><code>self</code><code>.clientAddress </code><code>=</code> <code>self</code><code>.s.accept()</code>
<code> </code><code>print</code><code>(</code><code>"accept connect from {0}"</code><code>.</code><code>format</code><code>(</code><code>self</code><code>.clientAddress))</code>
<code> </code><code>for</code> <code>i </code><code>in</code> <code>range</code><code>(</code><code>1</code><code>, </code><code>10</code><code>):</code>
<code> </code><code>conn.sendall(</code><code>"i = {0}"</code><code>.</code><code>format</code><code>(</code><code>str</code><code>(i)).encode(</code><code>"utf-8"</code><code>))</code>
<code> </code><code>self</code><code>.s.close()</code>
<code>class</code> <code>ClientSocketTest(InitSocketTest):</code>
<code> </code><code>self</code><code>.s.connect(</code><code>self</code><code>.address)</code>
<code> </code><code>stat </code><code>=</code> <code>1</code>
<code> </code><code>data </code><code>=</code> <code>self</code><code>.s.recv(</code><code>2048</code><code>)</code>
<code> </code><code>if</code> <code>len</code><code>(data)></code><code>0</code><code>:</code>
<code> </code><code>stat </code><code>=</code> <code>1</code>
<code> </code><code>print</code><code>(data.decode(</code><code>"utf-8"</code><code>))</code>
<code> </code><code>stat </code><code>+</code><code>=</code> <code>1</code>
<code> </code><code>time.sleep(</code><code>1</code><code>)</code>
<code> </code><code>if</code> <code>stat </code><code>=</code><code>=</code> <code>5</code><code>:</code>
# testserver.py
<code>from</code> <code>onlive.sockettest.util </code><code>import</code> <code>SocketServerTest </code>
<code>if</code> <code>__name__ </code><code>=</code><code>=</code> <code>'__main__'</code><code>: </code>
<code> </code><code>socketServer </code><code>=</code> <code>SocketServerTest(host</code><code>=</code><code>"0.0.0.0"</code><code>, port</code><code>=</code><code>9999</code><code>, </code><code>type</code><code>=</code><code>"tcp"</code><code>, backlog</code><code>=</code><code>5</code><code>) </code>
<code> </code><code>socketServer.run()</code>
# testclient.py
<code>from</code> <code>onlive.sockettest.util </code><code>import</code> <code>ClientSocketTest </code>
<code> </code><code>socketClient </code><code>=</code> <code>ClientSocketTest(host</code><code>=</code><code>"127.0.0.1"</code><code>, port</code><code>=</code><code>9999</code><code>, </code><code>type</code><code>=</code><code>"tcp"</code><code>) </code>
<code> </code><code>socketClient.run()</code>
<code></code>
本文转自 听丶飞鸟说 51CTO博客,原文链接:http://blog.51cto.com/286577399/2056083