少理 發表於 2019-10-21 17:31:00

python基础之socket与socketserver

<p style="box-sizing: border-box; font-family: &quot;Comic Sans MS&quot;, &quot;Microsoft YaHei&quot;, 黑体, 宋体, sans-serif; font-size: 16px !important"><strong style="box-sizing: border-box"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif; font-size: 14pt">---引入</span></strong></p>
<p style="box-sizing: border-box; font-family: &quot;Comic Sans MS&quot;, &quot;Microsoft YaHei&quot;, 黑体, 宋体, sans-serif; font-size: 16px !important"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif">Socket的英文原义是“孔”或“插座”,在Unix的进程通信机制中又称为‘套接字’。套接字实际上并不复杂,它是由一个ip地址以及一个端口号组成。Socket正如其英文原意那样,像一个多孔插座。一台主机犹如布满各种插座(ip地址)的房间,每个插座有很多插口(端口),通过这些插口接入电线(进程)我们可以烧水,看电视,玩电脑…… &nbsp;</span></p>
<p style="box-sizing: border-box; font-family: &quot;Comic Sans MS&quot;, &quot;Microsoft YaHei&quot;, 黑体, 宋体, sans-serif; font-size: 16px !important"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif"><span style="box-sizing: border-box; color: rgba(255, 0, 0, 1)">应用程序通常通过"套接字"向网络发出请求或者应答网络请求</span>。</span></p>
<p style="box-sizing: border-box; font-family: &quot;Comic Sans MS&quot;, &quot;Microsoft YaHei&quot;, 黑体, 宋体, sans-serif; font-size: 16px !important"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif">套接字的作用之一就是用来区分不同应用进程,当某个进程绑定了本机ip的某个端口,那么所有传送至这个ip地址上的这个端口的所有数据都会被内核送至该进程进行处理。<br style="box-sizing: border-box"></span></p>
<p style="box-sizing: border-box; font-family: &quot;Comic Sans MS&quot;, &quot;Microsoft YaHei&quot;, 黑体, 宋体, sans-serif; font-size: 16px !important"><strong style="box-sizing: border-box"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif; font-size: 14pt">---python中的socket</span></strong></p>
<p style="box-sizing: border-box; color: rgba(85, 85, 85, 1); font-size: 13.6364px; margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0; clear: both; height: auto; overflow: hidden; font-family: 宋体, &quot;Arial Narrow&quot;, arial, serif; line-height: 25.4545px"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif; font-size: 16px"><span class="replace_word" style="box-sizing: border-box; color: rgba(223, 52, 52, 1); font-weight: bold">Python</span>&nbsp;<span style="box-sizing: border-box; color: rgba(0, 0, 0, 1)">提供了两个基本的 socket 模块。</span></span></p>
<p style="box-sizing: border-box; color: rgba(85, 85, 85, 1); font-size: 13.6364px; margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0; clear: both; height: auto; overflow: hidden; font-family: 宋体, &quot;Arial Narrow&quot;, arial, serif; line-height: 25.4545px"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif; font-size: 16px; color: rgba(0, 0, 0, 1)">&nbsp; &nbsp;第一个是 Socket,它提供了标准的 BSD Sockets API。</span></p>
<p style="box-sizing: border-box; color: rgba(85, 85, 85, 1); font-size: 13.6364px; margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0; clear: both; height: auto; overflow: hidden; font-family: 宋体, &quot;Arial Narrow&quot;, arial, serif; line-height: 25.4545px"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif; font-size: 16px; color: rgba(0, 0, 0, 1)">&nbsp; &nbsp;第二个是 SocketServer, 它提供了服务器中心类,可以简化网络服务器的开发。</span></p>
<p style="box-sizing: border-box; color: rgba(85, 85, 85, 1); font-size: 13.6364px; margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0; clear: both; height: auto; overflow: hidden; font-family: 宋体, &quot;Arial Narrow&quot;, arial, serif; line-height: 25.4545px"><strong style="box-sizing: border-box"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif; font-size: 18px; color: rgba(0, 0, 0, 1)">----socket</span></strong></p>
<p style="box-sizing: border-box; color: rgba(85, 85, 85, 1); font-size: 13.6364px; margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0; clear: both; height: auto; overflow: hidden; font-family: 宋体, &quot;Arial Narrow&quot;, arial, serif; line-height: 25.4545px"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif; font-size: 16px; color: rgba(0, 0, 0, 1)">&nbsp;&nbsp; 先来说第一个。</span></p>
<p style="box-sizing: border-box; color: rgba(85, 85, 85, 1); font-size: 13.6364px; margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0; clear: both; height: auto; overflow: hidden; font-family: 宋体, &quot;Arial Narrow&quot;, arial, serif; line-height: 25.4545px"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif; font-size: 16px; color: rgba(0, 0, 0, 1)">我们知道,现在的应用程序大多为C/S架构,也就是分为客户端/服务器端。</span></p>
<p style="box-sizing: border-box; color: rgba(85, 85, 85, 1); font-size: 13.6364px; margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0; clear: both; height: auto; overflow: hidden; font-family: 宋体, &quot;Arial Narrow&quot;, arial, serif; line-height: 25.4545px"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif; font-size: 16px; color: rgba(0, 0, 0, 1)">  服务器端:服务器端进程需要申请套接字,然后自己绑定在这个套接字上,并对这个套接字进行监听。当有客户端发送数据了,则接受数据进行处理,处理完成后对客户端进行响应。</span></p>
<p style="box-sizing: border-box; color: rgba(85, 85, 85, 1); font-size: 13.6364px; margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0; clear: both; height: auto; overflow: hidden; font-family: 宋体, &quot;Arial Narrow&quot;, arial, serif; line-height: 25.4545px"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif; font-size: 16px; color: rgba(0, 0, 0, 1)">  客户端:客户端则相对简单些,客户端只需要申请一个套接字,然后通过这个套接字连接服务器端的套接字,连接建立后就可以进行后续操作了。<br style="box-sizing: border-box"></span></p>
<p style="box-sizing: border-box; color: rgba(85, 85, 85, 1); font-size: 13.6364px; margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0; clear: both; height: auto; overflow: hidden; font-family: 宋体, &quot;Arial Narrow&quot;, arial, serif; line-height: 25.4545px"><strong style="box-sizing: border-box"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif; font-size: 16px; color: rgba(0, 0, 0, 1)">python编写服务器端的步骤:</span></strong></p>
<p style="box-sizing: border-box; color: rgba(85, 85, 85, 1); font-size: 13.6364px; margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0; clear: both; height: auto; overflow: hidden; font-family: 宋体, &quot;Arial Narrow&quot;, arial, serif; line-height: 25.4545px"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif; font-size: 16px; color: rgba(0, 0, 0, 1)">&nbsp;&nbsp;<span style="box-sizing: border-box; color: rgba(225, 29, 197, 1)">1&nbsp; 创建套接字</span></span></p>
<div class="cnblogs_code" style="box-sizing: border-box">
<pre><span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">import</span><span style="box-sizing: border-box; line-height: 1.5 !important"> socket
s1</span>=<span style="box-sizing: border-box; line-height: 1.5 !important">socket.socket(family,type)
</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">family参数代表地址家族,可为AF_INET或AF_UNIX。AF_INET家族包括Internet地址,AF_UNIX家族用于同一台机器上的进程间通信。</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">
#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">type参数代表套接字类型,可为SOCK_STREAM(流套接字,就是TCP套接字)和SOCK_DGRAM(数据报套接字,就是UDP套接字)。 </span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">
#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">默认为family=AF_INETtype=SOCK_STREM    <br style="box-sizing: border-box">#返回一个整数描述符,用这个描述符来标识这个套接字</span></pre>
</div>
<p style="box-sizing: border-box; font-family: &quot;Comic Sans MS&quot;, &quot;Microsoft YaHei&quot;, 黑体, 宋体, sans-serif; font-size: 16px !important"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif">&nbsp;&nbsp;<span style="box-sizing: border-box; color: rgba(225, 29, 197, 1)">2&nbsp; 绑定套接字</span></span></p>
<div class="cnblogs_code" style="box-sizing: border-box">
<pre><span style="box-sizing: border-box; line-height: 1.5 !important">s1.bind( address )
</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">由AF_INET所创建的套接字,address地址必须是一个双元素元组,格式是(host,port)。host代表主机,port代表端口号。<br style="box-sizing: border-box">#如果端口号正在使用、主机名不正确或端口已被保留,bind方法将引发socket.error异常。 </span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">
#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">例: ('192.168.1.1',9999)</span></pre>
</div>
<p style="box-sizing: border-box; font-family: &quot;Comic Sans MS&quot;, &quot;Microsoft YaHei&quot;, 黑体, 宋体, sans-serif; font-size: 16px !important"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif">&nbsp;&nbsp;<span style="box-sizing: border-box; color: rgba(225, 29, 197, 1)">3&nbsp; 监听套接字</span></span></p>
<div class="cnblogs_code" style="box-sizing: border-box">
<pre><span style="box-sizing: border-box; line-height: 1.5 !important">s1.listen( backlog )
</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">backlog指定最多允许多少个客户连接到服务器。它的值至少为1。收到连接请求后,这些请求需要排队,如果队列满,就拒绝请求。 </span></pre>
</div>
<p style="box-sizing: border-box; font-family: &quot;Comic Sans MS&quot;, &quot;Microsoft YaHei&quot;, 黑体, 宋体, sans-serif; font-size: 16px !important"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif">&nbsp;&nbsp;<span style="box-sizing: border-box; color: rgba(225, 29, 197, 1)">4&nbsp; 等待接受连接</span></span></p>
<div class="cnblogs_code" style="box-sizing: border-box">
<pre>connection, address =<span style="box-sizing: border-box; line-height: 1.5 !important"> s1.accept()
</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">调用accept方法时,socket会时入“waiting”状态,也就是处于阻塞状态。客户请求连接时,方法建立连接并返回服务器。</span><span style="box-sizing: border-box; color: rgba(255, 0, 0, 1); line-height: 1.5 !important">
#accept方法返回一个含有两个元素的元组(connection,address)。
#第一个元素connection是所连接的客户端的socket对象(实际上是该对象的内存地址),服务器必须通过它与客户端通信;
#第二个元素 address是客户的Internet地址。</span></pre>
</div>
<p style="box-sizing: border-box; font-family: &quot;Comic Sans MS&quot;, &quot;Microsoft YaHei&quot;, 黑体, 宋体, sans-serif; font-size: 16px !important"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif">&nbsp;&nbsp;<span style="box-sizing: border-box; color: rgba(225, 29, 197, 1)">5&nbsp; 处理阶段</span></span></p>
<div class="cnblogs_code" style="box-sizing: border-box">
<pre><span style="box-sizing: border-box; line-height: 1.5 !important">connection.recv(bufsize[,flag])<br style="box-sizing: border-box"><span style="box-sizing: border-box; background-color: rgba(255, 255, 255, 1); color: rgba(0, 128, 0, 1); line-height: 1.5 !important">#注意此处为connection
</span></span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">接受套接字的数据。数据以字符串形式返回,bufsize指定最多可以接收的数量。flag提供有关消息的其他信息,通常可以忽略</span>
<span style="box-sizing: border-box; line-height: 1.5 !important">
connection.send(string[,flag])
</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于string的字节大小。即:可能未将指定内容全部发送。</span></pre>
</div>
<p style="box-sizing: border-box; font-family: &quot;Comic Sans MS&quot;, &quot;Microsoft YaHei&quot;, 黑体, 宋体, sans-serif; font-size: 16px !important"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif">&nbsp;&nbsp;<span style="box-sizing: border-box; color: rgba(225, 29, 197, 1)">6&nbsp; 传输结束,关闭连接</span></span></p>
<div class="cnblogs_code" style="box-sizing: border-box">
<pre><span style="box-sizing: border-box; line-height: 1.5 !important">s1.close()
</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">关闭套接字</span></pre>
</div>
<p style="box-sizing: border-box; font-family: &quot;Comic Sans MS&quot;, &quot;Microsoft YaHei&quot;, 黑体, 宋体, sans-serif; font-size: 16px !important"><strong style="box-sizing: border-box"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif">python编写客户端</span></strong></p>
<p style="box-sizing: border-box; font-family: &quot;Comic Sans MS&quot;, &quot;Microsoft YaHei&quot;, 黑体, 宋体, sans-serif; font-size: 16px !important"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif">&nbsp;&nbsp;<span style="box-sizing: border-box; color: rgba(225, 29, 197, 1)">1&nbsp; 创建socket对象</span></span></p>
<div class="cnblogs_code" style="box-sizing: border-box">
<pre><span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">import</span><span style="box-sizing: border-box; line-height: 1.5 !important"> socket
s2</span>=socket.socket()</pre>
</div>
<p style="box-sizing: border-box; font-family: &quot;Comic Sans MS&quot;, &quot;Microsoft YaHei&quot;, 黑体, 宋体, sans-serif; font-size: 16px !important"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif">&nbsp;&nbsp;<span style="box-sizing: border-box; color: rgba(225, 29, 197, 1)">2&nbsp; 连接至服务器端</span></span></p>
<div class="cnblogs_code" style="box-sizing: border-box">
<pre><span style="box-sizing: border-box; line-height: 1.5 !important">s2.connect(address)
</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">连接到address处的套接字。一般,address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。</span></pre>
</div>
<p style="box-sizing: border-box; font-family: &quot;Comic Sans MS&quot;, &quot;Microsoft YaHei&quot;, 黑体, 宋体, sans-serif; font-size: 16px !important"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif">&nbsp;&nbsp;<span style="box-sizing: border-box; color: rgba(225, 29, 197, 1)">3&nbsp; 处理阶段</span></span></p>
<div class="cnblogs_code" style="box-sizing: border-box">
<pre><span style="box-sizing: border-box; line-height: 1.5 !important">s2.recv(bufsize[,flag])
</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">接受套接字的数据。数据以字符串形式返回,bufsize指定最多可以接收的数量。flag提供有关消息的其他信息,通常可以忽略</span>
<span style="box-sizing: border-box; line-height: 1.5 !important">
s2.send(string[,flag])
</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于string的字节大小。即:可能未将指定内容全部发送。</span></pre>
</div>
<p style="box-sizing: border-box; font-family: &quot;Comic Sans MS&quot;, &quot;Microsoft YaHei&quot;, 黑体, 宋体, sans-serif; font-size: 16px !important"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif">&nbsp;&nbsp;<span style="box-sizing: border-box; color: rgba(225, 29, 197, 1)">4&nbsp; 连接结束,关闭套接字</span></span></p>
<div class="cnblogs_code" style="box-sizing: border-box">
<pre>s2.close()</pre>
</div>
<p style="box-sizing: border-box; color: rgba(85, 85, 85, 1); font-size: 13.6364px; margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0; clear: both; height: auto; overflow: hidden; font-family: 宋体, &quot;Arial Narrow&quot;, arial, serif; line-height: 25.4545px"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif; font-size: 16px; color: rgba(51, 51, 51, 1)">socket中还有许多方法 :<br style="box-sizing: border-box"></span></p>
<p style="box-sizing: border-box; color: rgba(85, 85, 85, 1); font-size: 13.6364px; margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0; clear: both; height: auto; overflow: hidden; font-family: 宋体, &quot;Arial Narrow&quot;, arial, serif; line-height: 25.4545px">&nbsp;</p>
<div class="cnblogs_code" style="box-sizing: border-box">
<pre>socket.getaddrinfo(host, port, family=0, type=0, proto=0, flags=0) <span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">获取要连接的对端主机地址</span>
<span style="box-sizing: border-box; line-height: 1.5 !important">
sk.bind(address)
将套接字绑定到地址。address地址的格式取决于地址族。在AF_INET下,以元组(host,port)的形式表示地址。
<br style="box-sizing: border-box">sk.listen(backlog)
开始监听传入连接。backlog指定在拒绝连接之前,可以挂起的最大连接数量。
backlog等于5,表示内核已经接到了连接请求,但服务器还没有调用accept进行处理的连接个数最大为5,这个值不能无限大,因为要在内核中维护连接队列

sk.setblocking(bool)
是否阻塞(默认True),如果设置False,那么accept和recv时一旦无数据,则报错。
<br style="box-sizing: border-box">sk.accept()
接受连接并返回(conn,address),其中conn是新的套接字对象,可以用来接收和发送数据。address是连接客户端的地址。接收TCP 客户的连接(阻塞式)等待连接的到来

sk.connect(address)
连接到address处的套接字。一般,address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。

sk.connect_ex(address)
同上,只不过会有返回值,连接成功时返回 0 ,连接失败时候返回编码,例如:</span>10061<span style="box-sizing: border-box; line-height: 1.5 !important">

sk.close()
关闭套接字

sk.recv(bufsize[,flag])
接受套接字的数据。数据以字符串形式返回,bufsize指定最多可以接收的数量。flag提供有关消息的其他信息,通常可以忽略。

sk.recvfrom(bufsize[.flag])
与recv()类似,但返回值是(data,address)。其中data是包含接收数据的字符串,address是发送数据的套接字地址。

sk.send(string[,flag])
将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于string的字节大小。即:可能未将指定内容全部发送。

sk.sendall(string[,flag])
将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。内部通过递归调用send,将所有内容发送出去。

sk.sendto(string[,flag],address)
将数据发送到套接字,address是形式为(ipaddr,port)的元组,指定远程地址。返回值是发送的字节数。该函数主要用于UDP协议。

sk.settimeout(timeout)
设置套接字操作的超时期,timeout是一个浮点数,单位是秒。值为None表示没有超时期。一般,超时期应该在刚创建套接字时设置,<br style="box-sizing: border-box">因为它们可能用于连接的操作(如 client 连接最多等待5s )

sk.getpeername()
返回连接套接字的远程地址。返回值通常是元组(ipaddr,port)。

sk.getsockname()
返回套接字自己的地址。通常是一个元组(ipaddr,port)

sk.fileno()
套接字的文件描述符

socket.sendfile(file, offset</span>=0, count=<span style="box-sizing: border-box; line-height: 1.5 !important">None)
发送文件 </span></pre>
</div>
<p style="box-sizing: border-box; color: rgba(85, 85, 85, 1); font-size: 13.6364px; margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0; clear: both; height: auto; overflow: hidden; font-family: 宋体, &quot;Arial Narrow&quot;, arial, serif; line-height: 25.4545px">&nbsp;</p>
<p style="box-sizing: border-box; color: rgba(85, 85, 85, 1); font-size: 13.6364px; margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0; clear: both; height: auto; overflow: hidden; font-family: 宋体, &quot;Arial Narrow&quot;, arial, serif; line-height: 25.4545px">&nbsp;</p>
<p style="box-sizing: border-box; color: rgba(85, 85, 85, 1); font-size: 13.6364px; margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0; clear: both; height: auto; overflow: hidden; font-family: 宋体, &quot;Arial Narrow&quot;, arial, serif; line-height: 25.4545px"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif; font-size: 16px; color: rgba(0, 0, 0, 1)">好了,介绍完socket现在该介绍socketserver了。</span></p>
<p style="box-sizing: border-box; color: rgba(85, 85, 85, 1); font-size: 13.6364px; margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0; clear: both; height: auto; overflow: hidden; font-family: 宋体, &quot;Arial Narrow&quot;, arial, serif; line-height: 25.4545px"><span style="box-sizing: border-box; font-size: 18px"><strong style="box-sizing: border-box"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif; color: rgba(0, 0, 0, 1)">----socketserver</span></strong></span></p>
<p style="box-sizing: border-box; color: rgba(85, 85, 85, 1); font-size: 13.6364px; margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0; clear: both; height: auto; overflow: hidden; font-family: 宋体, &quot;Arial Narrow&quot;, arial, serif; line-height: 25.4545px"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif; font-size: 16px; color: rgba(0, 0, 0, 1)">  虽说用Python编写简单的网络程序很方便,但复杂一点的网络程序还是用现成的框架比较 好。这样就可以专心事务逻辑,而不是套接字的各种细节。SocketServer模块简化了编写网络服务程序的任务。同时SocketServer模块也 是Python标准库中很多服务器框架的基础。</span></p>
<p style="box-sizing: border-box; color: rgba(85, 85, 85, 1); font-size: 13.6364px; margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0; clear: both; height: auto; overflow: hidden; font-family: 宋体, &quot;Arial Narrow&quot;, arial, serif; line-height: 25.4545px"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif; font-size: 16px; color: rgba(0, 0, 0, 1)">socketserver在python2中为SocketServer,在python3种取消了首字母大写,改名为socketserver。</span></p>
<p style="box-sizing: border-box; color: rgba(85, 85, 85, 1); font-size: 13.6364px; margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0; clear: both; height: auto; overflow: hidden; font-family: 宋体, &quot;Arial Narrow&quot;, arial, serif; line-height: 25.4545px"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif; font-size: 16px; color: rgba(0, 0, 0, 1)">socketserver中包含了两种类,<span style="box-sizing: border-box; color: rgba(0, 0, 255, 1)">一种为服务类(server class)</span>,一种为<span style="box-sizing: border-box; color: rgba(0, 0, 255, 1)">请求处理类(request handle class)</span>。前者提供了许多方法:像绑定,监听,运行…… (也就是<span style="box-sizing: border-box; color: rgba(0, 0, 255, 1)">建立连接</span>的过程) 后者则专注于如何处理用户所发送的数据(也就是事务逻辑)。</span></p>
<p style="box-sizing: border-box; color: rgba(85, 85, 85, 1); font-size: 13.6364px; margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0; clear: both; height: auto; overflow: hidden; font-family: 宋体, &quot;Arial Narrow&quot;, arial, serif; line-height: 25.4545px"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif; font-size: 16px; color: rgba(0, 0, 0, 1)">  <span style="box-sizing: border-box; color: rgba(255, 0, 0, 1)">一般情况下,所有的服务,都是先建立连接,也就是建立一个服务类的实例,然后开始处理用户请求,也就是建立一个请求处理类的实例</span>。<br style="box-sizing: border-box"></span></p>
<p style="box-sizing: border-box; color: rgba(85, 85, 85, 1); font-size: 13.6364px; margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0; clear: both; height: auto; overflow: hidden; font-family: 宋体, &quot;Arial Narrow&quot;, arial, serif; line-height: 25.4545px">&nbsp;</p>
<p style="box-sizing: border-box; color: rgba(85, 85, 85, 1); font-size: 13.6364px; margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0; clear: both; height: auto; overflow: hidden; font-family: 宋体, &quot;Arial Narrow&quot;, arial, serif; line-height: 25.4545px"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif; font-size: 16px; color: rgba(0, 0, 0, 1)">我们分析一下源码,来看一看服务类是如何与请求处理类建立联系的。</span></p>
<div class="cnblogs_code" style="box-sizing: border-box">
<pre><span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">class</span><span style="box-sizing: border-box; line-height: 1.5 !important"> BaseServer:<br style="box-sizing: border-box"><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">#我们创建服务类时,需要指定(地址,端口),服务处理类。
    </span></span><span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">def</span> <span style="box-sizing: border-box; color: rgba(128, 0, 128, 1); line-height: 1.5 !important">__init__</span><span style="box-sizing: border-box; line-height: 1.5 !important">(self, server_address, RequestHandlerClass):
      </span><span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">"""</span><span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">Constructor.May be extended, do not override.</span><span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">"""</span><span style="box-sizing: border-box; line-height: 1.5 !important">
      self.server_address </span>=<span style="box-sizing: border-box; line-height: 1.5 !important"> server_address
      self.RequestHandlerClass </span>=<span style="box-sizing: border-box; line-height: 1.5 !important"> RequestHandlerClass
      self.</span><span style="box-sizing: border-box; color: rgba(128, 0, 128, 1); line-height: 1.5 !important">__is_shut_down</span> =<span style="box-sizing: border-box; line-height: 1.5 !important"> threading.Event()
      self.</span><span style="box-sizing: border-box; color: rgba(128, 0, 128, 1); line-height: 1.5 !important">__shutdown_request</span> =<span style="box-sizing: border-box; line-height: 1.5 !important"> False
</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">…………此处省略n多代码,当我们执行server_forever方法时,里面就会调用很多服务类中的其他方法,但最终会调用<span style="box-sizing: border-box; color: rgba(255, 0, 0, 1); line-height: 1.5 !important">finish_request</span>方法。</span>

    <span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">def</span><span style="box-sizing: border-box; line-height: 1.5 !important"> finish_request(self, request, client_address):
      </span><span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">"""</span><span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">Finish one request by instantiating RequestHandlerClass.</span><span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">"""</span><span style="box-sizing: border-box; line-height: 1.5 !important">
      self.RequestHandlerClass(request, client_address, self)
<span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">#finish_request方法中执行了self.RequestHandlerClass(request, client_address, self)。self.RequestHandlerClass是什么呢?<br style="box-sizing: border-box">#self.RequestHandlerClass = RequestHandlerClass(就在__init__方法中)。所以finish_request方法本质上就是创建了一个服务处理实例。</span>
<br style="box-sizing: border-box"><br style="box-sizing: border-box"></span><span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">class</span><span style="box-sizing: border-box; line-height: 1.5 !important"> BaseRequestHandler:
    </span><span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">def</span> <span style="box-sizing: border-box; color: rgba(128, 0, 128, 1); line-height: 1.5 !important">__init__</span><span style="box-sizing: border-box; line-height: 1.5 !important">(self, request, client_address, server):
      self.request </span>=<span style="box-sizing: border-box; line-height: 1.5 !important"> request
      self.client_address </span>=<span style="box-sizing: border-box; line-height: 1.5 !important"> client_address
      self.server </span>=<span style="box-sizing: border-box; line-height: 1.5 !important"> server
      self.setup()
      </span><span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">try</span><span style="box-sizing: border-box; line-height: 1.5 !important">:
            self.handle()
      </span><span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">finally</span><span style="box-sizing: border-box; line-height: 1.5 !important">:
            self.finish()<br style="box-sizing: border-box"><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">#当我们创建服务处理类实例时,就会运行handle()方法,而handle()方法则一般是我们处理事务逻辑的代码块。
</span></span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">…………此处省略n多代码</span></pre>
</div>
<p style="box-sizing: border-box; color: rgba(85, 85, 85, 1); font-size: 13.6364px; margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0; clear: both; height: auto; overflow: hidden; font-family: 宋体, &quot;Arial Narrow&quot;, arial, serif; line-height: 25.4545px">&nbsp;</p>
<p style="box-sizing: border-box; color: rgba(85, 85, 85, 1); font-size: 13.6364px; margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0; clear: both; height: auto; overflow: hidden; font-family: 宋体, &quot;Arial Narrow&quot;, arial, serif; line-height: 25.4545px"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif; font-size: 16px; color: rgba(0, 0, 0, 1)">我们接下来介绍一下这两个类</span></p>
<p style="box-sizing: border-box; color: rgba(85, 85, 85, 1); font-size: 13.6364px; margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0; clear: both; height: auto; overflow: hidden; font-family: 宋体, &quot;Arial Narrow&quot;, arial, serif; line-height: 25.4545px"><span style="box-sizing: border-box; font-size: 16px"><strong style="box-sizing: border-box"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif; color: rgba(0, 0, 0, 1)">先来看服务类:</span></strong></span></p>
<p style="box-sizing: border-box; color: rgba(85, 85, 85, 1); font-size: 13.6364px; margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0; clear: both; height: auto; overflow: hidden; font-family: 宋体, &quot;Arial Narrow&quot;, arial, serif; line-height: 25.4545px"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif; font-size: 16px; color: rgba(0, 0, 0, 1)">5种类型:BaseServer,TCPServer,UnixStreamServer,UDPServer,UnixDatagramServer。</span></p>
<p style="box-sizing: border-box; color: rgba(85, 85, 85, 1); font-size: 13.6364px; margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0; clear: both; height: auto; overflow: hidden; font-family: 宋体, &quot;Arial Narrow&quot;, arial, serif; line-height: 25.4545px"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif; font-size: 16px; color: rgba(0, 0, 0, 1)">BaseServer不直接对外服务。</span></p>
<p style="box-sizing: border-box; font-family: &quot;Comic Sans MS&quot;, &quot;Microsoft YaHei&quot;, 黑体, 宋体, sans-serif; font-size: 16px !important"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif">TCPServer针对TCP套接字流</span></p>
<p style="box-sizing: border-box; font-family: &quot;Comic Sans MS&quot;, &quot;Microsoft YaHei&quot;, 黑体, 宋体, sans-serif; font-size: 16px !important"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif">UDPServer针对UDP数据报套接字</span></p>
<p style="box-sizing: border-box; font-family: &quot;Comic Sans MS&quot;, &quot;Microsoft YaHei&quot;, 黑体, 宋体, sans-serif; font-size: 16px !important"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif">UnixStreamServer和UnixDatagramServer针对UNIX域套接字,不常用。</span></p>
<p style="box-sizing: border-box; font-family: &quot;Comic Sans MS&quot;, &quot;Microsoft YaHei&quot;, 黑体, 宋体, sans-serif; font-size: 16px !important"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif">他们之间的继承关系:</span></p>
<p style="box-sizing: border-box; font-family: &quot;Comic Sans MS&quot;, &quot;Microsoft YaHei&quot;, 黑体, 宋体, sans-serif; font-size: 16px !important"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif"><img src="https://images2015.cnblogs.com/blog/933924/201606/933924-20160603105943914-13081191.png"></span></p>
<p style="box-sizing: border-box; color: rgba(85, 85, 85, 1); font-size: 13.6364px; margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0; clear: both; height: auto; overflow: hidden; font-family: 宋体, &quot;Arial Narrow&quot;, arial, serif; line-height: 25.4545px">&nbsp;</p>
<p style="box-sizing: border-box; color: rgba(85, 85, 85, 1); font-size: 13.6364px; margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0; clear: both; height: auto; overflow: hidden; font-family: 宋体, &quot;Arial Narrow&quot;, arial, serif; line-height: 25.4545px">&nbsp;</p>
<p style="box-sizing: border-box; font-family: &quot;Comic Sans MS&quot;, &quot;Microsoft YaHei&quot;, 黑体, 宋体, sans-serif; font-size: 16px !important"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif">服务类的方法:</span></p>
<div class="cnblogs_code" style="box-sizing: border-box">
<div id="cnblogs_code_open_65d72170-7681-48b5-8e7a-6a8e8f099312" class="cnblogs_code_hide" style="box-sizing: border-box; display: block">
<div class="cnblogs_code_toolbar" style="box-sizing: border-box; margin-top: 5px">&nbsp;</div>
<pre>   <span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">class</span><span style="box-sizing: border-box; line-height: 1.5 !important"> SocketServer.BaseServer:这是模块中的所有服务器对象的超类。它定义了接口,如下所述,但是大多数的方法不实现,在子类中进行细化。

    BaseServer.fileno():返回服务器监听套接字的整数文件描述符。通常用来传递给select.select(), 以允许一个进程监视多个服务器。

    BaseServer.handle_request():处理单个请求。处理顺序:get_request(), verify_request(), process_request()。如果用户提供handle()方法抛出异常,将调用服务器的handle_error()方法。如果self.timeout内没有请求收到, 将调用handle_timeout()并返回handle_request()。

    BaseServer.serve_forever(poll_interval</span>=0.5<span style="box-sizing: border-box; line-height: 1.5 !important">): 处理请求,直到一个明确的shutdown()请求。每poll_interval秒轮询一次shutdown。忽略self.timeout。如果你需要做周期性的任务,建议放置在其他线程。

    BaseServer.shutdown():告诉serve_forever()循环停止并等待其停止。python2.6版本。

    BaseServer.address_family: 地址家族,比如socket.AF_INET和socket.AF_UNIX。

    BaseServer.RequestHandlerClass:用户提供的请求处理类,这个类为每个请求创建实例。

    BaseServer.server_address:服务器侦听的地址。格式根据协议家族地址的各不相同,请参阅socket模块的文档。

    BaseServer.socketSocket:服务器上侦听传入的请求socket对象的服务器。

服务器类支持下面的类变量:

    BaseServer.allow_reuse_address:服务器是否允许地址的重用。默认为false ,并且可在子类中更改。

    BaseServer.request_queue_size

请求队列的大小。如果单个请求需要很长的时间来处理,服务器忙时请求被放置到队列中,最多可以放request_queue_size个。一旦队列已满,来自客户端的请求将得到 “Connection denied”错误。默认值通常为5 ,但可以被子类覆盖。

    BaseServer.socket_type:服务器使用的套接字类型; socket.SOCK_STREAM和socket.SOCK_DGRAM等。

    BaseServer.timeout:超时时间,以秒为单位,或 None表示没有超时。如果handle_request()在timeout内没有收到请求,将调用handle_timeout()。

下面方法可以被子类重载,它们对服务器对象的外部用户没有影响。

    BaseServer.finish_request():实际处理RequestHandlerClass发起的请求并调用其handle()方法。 常用。

    BaseServer.get_request():接受socket请求,并返回二元组包含要用于与客户端通信的新socket对象,以及客户端的地址。

    BaseServer.handle_error(request, client_address):如果RequestHandlerClass的handle()方法抛出异常时调用。默认操作是打印traceback到标准输出,并继续处理其他请求。

    BaseServer.handle_timeout():超时处理。默认对于forking服务器是收集退出的子进程状态,threading服务器则什么都不做。

    BaseServer.process_request(request, client_address) :调用finish_request()创建RequestHandlerClass的实例。如果需要,此功能可以创建新的进程或线程来处理请求,ForkingMixIn和ThreadingMixIn类做到这点。常用。

    BaseServer.server_activate():通过服务器的构造函数来激活服务器。默认的行为只是监听服务器套接字。可重载。

    BaseServer.server_bind():通过服务器的构造函数中调用绑定socket到所需的地址。可重载。

    BaseServer.verify_request(request, client_address):返回一个布尔值,如果该值为True ,则该请求将被处理,反之请求将被拒绝。此功能可以重写来实现对服务器的访问控制。默认的实现始终返回True。client_address可以限定客户端,比如只处理指定ip区间的请求。 常用。</span></pre>
<div class="cnblogs_code_toolbar" style="box-sizing: border-box; margin-top: 5px">&nbsp;</div>
</div>
</div>
<p style="box-sizing: border-box; font-family: &quot;Comic Sans MS&quot;, &quot;Microsoft YaHei&quot;, 黑体, 宋体, sans-serif; font-size: 16px !important"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif">这个几个服务类都是同步处理请求的:一个请求没处理完不能处理下一个请求。要想支持异步模型,可以利用多继承让server类继承ForkingMixIn 或 ThreadingMixIn mix-in classes。</span></p>
<p style="box-sizing: border-box; font-family: &quot;Comic Sans MS&quot;, &quot;Microsoft YaHei&quot;, 黑体, 宋体, sans-serif; font-size: 16px !important"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif; color: rgba(0, 0, 255, 1)">ForkingMixIn利用多进程(分叉)实现异步。</span></p>
<p style="box-sizing: border-box; font-family: &quot;Comic Sans MS&quot;, &quot;Microsoft YaHei&quot;, 黑体, 宋体, sans-serif; font-size: 16px !important"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif; color: rgba(0, 0, 255, 1)">ThreadingMixIn利用多线程实现异步。</span></p>
<p style="box-sizing: border-box; color: rgba(85, 85, 85, 1); font-size: 13.6364px; margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0; clear: both; height: auto; overflow: hidden; font-family: 宋体, &quot;Arial Narrow&quot;, arial, serif; line-height: 25.4545px">&nbsp;</p>
<p style="box-sizing: border-box; color: rgba(85, 85, 85, 1); font-size: 13.6364px; margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0; clear: both; height: auto; overflow: hidden; font-family: 宋体, &quot;Arial Narrow&quot;, arial, serif; line-height: 25.4545px"><span style="box-sizing: border-box; color: rgba(0, 0, 0, 1)"><strong style="box-sizing: border-box"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif; font-size: 16px">请求处理器类:</span></strong></span></p>
<p style="box-sizing: border-box; font-family: &quot;Comic Sans MS&quot;, &quot;Microsoft YaHei&quot;, 黑体, 宋体, sans-serif; font-size: 16px !important"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif">要实现一项服务,还必须派生一个handler class请求处理类,并重写父类的handle()方法。handle方法就是用来专门是处理请求的。该模块是通过服务类和请求处理类组合来处理请求的。</span></p>
<p style="box-sizing: border-box; font-family: &quot;Comic Sans MS&quot;, &quot;Microsoft YaHei&quot;, 黑体, 宋体, sans-serif; font-size: 16px !important"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif">SocketServer模块提供的请求处理类有BaseRequestHandler,以及它的派生类StreamRequestHandler和DatagramRequestHandler。从名字看出可以一个处理流式套接字,一个处理数据报套接字。</span></p>
<p style="box-sizing: border-box; font-family: &quot;Comic Sans MS&quot;, &quot;Microsoft YaHei&quot;, 黑体, 宋体, sans-serif; font-size: 16px !important">&nbsp;</p>
<p style="box-sizing: border-box; font-family: &quot;Comic Sans MS&quot;, &quot;Microsoft YaHei&quot;, 黑体, 宋体, sans-serif; font-size: 16px !important"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif">请求处理类有三种方法:</span></p>
<dl class="method" style="box-sizing: border-box; color: rgba(75, 75, 75, 1); font-family: &quot;Comic Sans MS&quot;, &quot;Microsoft YaHei&quot;, 黑体, 宋体, sans-serif; font-size: 13px"><dt id="socketserver.BaseRequestHandler.setup" style="box-sizing: border-box"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif; font-size: 16px"><strong style="box-sizing: border-box"><code class="descname" style="box-sizing: border-box">setup</code><span class="sig-paren" style="box-sizing: border-box">(<span class="sig-paren" style="box-sizing: border-box">)</span></span></strong></span></dt><dd style="box-sizing: border-box">
<p style="box-sizing: border-box; color: rgba(0, 0, 0, 1); font-size: 16px !important"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif">Called before the&nbsp;<code class="xref py py-meth docutils literal" style="box-sizing: border-box"><span class="pre" style="box-sizing: border-box">handle()</span></code>&nbsp;method to perform any initialization actions required. The default implementation does nothing.</span></p>
<p style="box-sizing: border-box; color: rgba(0, 0, 0, 1); font-size: 16px !important"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif">也就是在handle()之前被调用,主要的作用就是执行处理请求之前的初始化相关的各种工作。默认不会做任何事。(如果想要让其做一些事的话,就要程序员在自己的请求处理器中覆盖这个方法(因为一般自定义的请求处理器都要继承python中提供的BaseRequestHandler,ps:下文会提到的),然后往里面添加东西即可)</span></p>
</dd></dl><dl class="method" style="box-sizing: border-box; color: rgba(75, 75, 75, 1); font-family: &quot;Comic Sans MS&quot;, &quot;Microsoft YaHei&quot;, 黑体, 宋体, sans-serif; font-size: 13px"><dt id="socketserver.BaseRequestHandler.handle" style="box-sizing: border-box"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif; font-size: 16px"><strong style="box-sizing: border-box"><code class="descname" style="box-sizing: border-box">handle</code><span class="sig-paren" style="box-sizing: border-box">(<span class="sig-paren" style="box-sizing: border-box">)</span></span></strong></span></dt><dd style="box-sizing: border-box">
<p style="box-sizing: border-box; color: rgba(0, 0, 0, 1); font-size: 16px !important"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif">This function must do all the work required to service a request. The default implementation does nothing. Several instance attributes are available to it; the request is available as&nbsp;<code class="xref py py-attr docutils literal" style="box-sizing: border-box"><span class="pre" style="box-sizing: border-box">self.request</span></code>; the client address as&nbsp;<code class="xref py py-attr docutils literal" style="box-sizing: border-box"><span class="pre" style="box-sizing: border-box">self.client_address</span></code>; and the server instance as&nbsp;<code class="xref py py-attr docutils literal" style="box-sizing: border-box"><span class="pre" style="box-sizing: border-box">self.server</span></code>, in case it needs access to per-server information.</span></p>
<p style="box-sizing: border-box; color: rgba(0, 0, 0, 1); font-size: 16px !important"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif">The type of&nbsp;<code class="xref py py-attr docutils literal" style="box-sizing: border-box"><span class="pre" style="box-sizing: border-box">self.request</span></code>&nbsp;is different for datagram or stream services. For stream services,<code class="xref py py-attr docutils literal" style="box-sizing: border-box"><span class="pre" style="box-sizing: border-box">self.request</span></code>&nbsp;is a socket object; for datagram services,&nbsp;<code class="xref py py-attr docutils literal" style="box-sizing: border-box"><span class="pre" style="box-sizing: border-box">self.request</span></code>&nbsp;is a pair of string and socket.</span></p>
<p style="box-sizing: border-box; color: rgba(0, 0, 0, 1); font-size: 16px !important"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif">handle()的工作就是做那些所有与处理请求相关的工作。默认也不会做任何事。他有数个实例参数:self.request&nbsp;&nbsp;&nbsp; self.client_address&nbsp;&nbsp; self.server</span></p>
</dd></dl><dl class="method" style="box-sizing: border-box; color: rgba(75, 75, 75, 1); font-family: &quot;Comic Sans MS&quot;, &quot;Microsoft YaHei&quot;, 黑体, 宋体, sans-serif; font-size: 13px"><dt id="socketserver.BaseRequestHandler.finish" style="box-sizing: border-box"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif; font-size: 16px"><strong style="box-sizing: border-box"><code class="descname" style="box-sizing: border-box">finish</code><span class="sig-paren" style="box-sizing: border-box">(<span class="sig-paren" style="box-sizing: border-box">)</span></span></strong></span></dt><dd style="box-sizing: border-box">
<p style="box-sizing: border-box; color: rgba(0, 0, 0, 1); font-size: 16px !important"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif">Called after the&nbsp;<code class="xref py py-meth docutils literal" style="box-sizing: border-box"><span class="pre" style="box-sizing: border-box">handle()</span></code>&nbsp;method to perform any clean-up actions required. The default implementation does nothing. If&nbsp;<code class="xref py py-meth docutils literal" style="box-sizing: border-box"><span class="pre" style="box-sizing: border-box">setup()</span></code>&nbsp;raises an exception, this function will not be called.</span></p>
<p style="box-sizing: border-box; color: rgba(0, 0, 0, 1); font-size: 16px !important"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif">在handle()方法之后会被调用,他的作用就是执行当处理完请求后的清理工作,默认不会做任何事</span><img id="code_img_opened_84c06cf1-cba7-4ef0-b7aa-5b59a2ef084f" class="code_img_opened lazyload" style="box-sizing: border-box; max-width: 900px; height: auto" alt="" data-src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif"></p>
</dd></dl>
<div class="cnblogs_code" style="box-sizing: border-box">
<div id="cnblogs_code_open_84c06cf1-cba7-4ef0-b7aa-5b59a2ef084f" class="cnblogs_code_hide" style="box-sizing: border-box; display: block">
<pre><span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">class</span><span style="box-sizing: border-box; line-height: 1.5 !important"> BaseRequestHandler:

    </span><span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">"""</span><span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">Base class for request handler classes.

    This class is instantiated for each request to be handled.The
    constructor sets the instance variables request, client_address
    and server, and then calls the handle() method.To implement a
    specific service, all you need to do is to derive a class which
    defines a handle() method.

    The handle() method can find the request as self.request, the
    client address as self.client_address, and the server (in case it
    needs access to per-server information) as self.server.Since a
    separate instance is created for each request, the handle() method
    can define arbitrary other instance variariables.

    </span><span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">"""</span>

    <span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">def</span> <span style="box-sizing: border-box; color: rgba(128, 0, 128, 1); line-height: 1.5 !important">__init__</span><span style="box-sizing: border-box; line-height: 1.5 !important">(self, request, client_address, server):
      self.request </span>=<span style="box-sizing: border-box; line-height: 1.5 !important"> request
      self.client_address </span>=<span style="box-sizing: border-box; line-height: 1.5 !important"> client_address
      self.server </span>=<span style="box-sizing: border-box; line-height: 1.5 !important"> server
      self.setup()
      </span><span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">try</span><span style="box-sizing: border-box; line-height: 1.5 !important">:
            self.handle()
      </span><span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">finally</span><span style="box-sizing: border-box; line-height: 1.5 !important">:
            self.finish()

    </span><span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">def</span><span style="box-sizing: border-box; line-height: 1.5 !important"> setup(self):
      </span><span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">pass</span>

    <span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">def</span><span style="box-sizing: border-box; line-height: 1.5 !important"> handle(self):
      </span><span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">pass</span>

    <span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">def</span><span style="box-sizing: border-box; line-height: 1.5 !important"> finish(self):
      </span><span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">pass</span>


<span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important"> The following two classes make it possible to use the same service</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">
#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important"> class for stream or datagram servers.</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">
#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important"> Each class sets up these instance variables:</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">
#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important"> - rfile: a file object from which receives the request is read</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">
#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important"> - wfile: a file object to which the reply is written</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">
#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important"> When the handle() method returns, wfile is flushed properly</span>


<span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">class</span><span style="box-sizing: border-box; line-height: 1.5 !important"> StreamRequestHandler(BaseRequestHandler):

    </span><span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">"""</span><span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">Define self.rfile and self.wfile for stream sockets.</span><span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">"""</span>

    <span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important"> Default buffer sizes for rfile, wfile.</span>
    <span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important"> We default rfile to buffered because otherwise it could be</span>
    <span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important"> really slow for large data (a getc() call per byte); we make</span>
    <span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important"> wfile unbuffered because (a) often after a write() we want to</span>
    <span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important"> read and we need to flush the line; (b) big writes to unbuffered</span>
    <span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important"> files are typically optimized by stdio even when big reads</span>
    <span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important"> aren't.</span>
    rbufsize = -1<span style="box-sizing: border-box; line-height: 1.5 !important">
    wbufsize </span>=<span style="box-sizing: border-box; line-height: 1.5 !important"> 0

    </span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important"> A timeout to apply to the request socket, if not None.</span>
    timeout =<span style="box-sizing: border-box; line-height: 1.5 !important"> None

    </span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important"> Disable nagle algorithm for this socket, if True.</span>
    <span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important"> Use only when wbufsize != 0, to avoid small packets.</span>
    disable_nagle_algorithm =<span style="box-sizing: border-box; line-height: 1.5 !important"> False

    </span><span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">def</span><span style="box-sizing: border-box; line-height: 1.5 !important"> setup(self):
      self.connection </span>=<span style="box-sizing: border-box; line-height: 1.5 !important"> self.request
      </span><span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">if</span> self.timeout <span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">is</span> <span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">not</span><span style="box-sizing: border-box; line-height: 1.5 !important"> None:
            self.connection.settimeout(self.timeout)
      </span><span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">if</span><span style="box-sizing: border-box; line-height: 1.5 !important"> self.disable_nagle_algorithm:
            self.connection.setsockopt(socket.IPPROTO_TCP,
                                       socket.TCP_NODELAY, True)
      self.rfile </span>= self.connection.makefile(<span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">'</span><span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">rb</span><span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">'</span><span style="box-sizing: border-box; line-height: 1.5 !important">, self.rbufsize)
      self.wfile </span>= self.connection.makefile(<span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">'</span><span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">wb</span><span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">'</span><span style="box-sizing: border-box; line-height: 1.5 !important">, self.wbufsize)

    </span><span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">def</span><span style="box-sizing: border-box; line-height: 1.5 !important"> finish(self):
      </span><span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">if</span> <span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">not</span><span style="box-sizing: border-box; line-height: 1.5 !important"> self.wfile.closed:
            </span><span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">try</span><span style="box-sizing: border-box; line-height: 1.5 !important">:
                self.wfile.flush()
            </span><span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">except</span><span style="box-sizing: border-box; line-height: 1.5 !important"> socket.error:
                </span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important"> An final socket error may have occurred here, such as</span>
                <span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important"> the local error ECONNABORTED.</span>
                <span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">pass</span><span style="box-sizing: border-box; line-height: 1.5 !important">
      self.wfile.close()
      self.rfile.close()


</span><span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">class</span><span style="box-sizing: border-box; line-height: 1.5 !important"> DatagramRequestHandler(BaseRequestHandler):

    </span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important"> XXX Regrettably, I cannot get this working on Linux;</span>
    <span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important"> s.recvfrom() doesn't return a meaningful client address.</span>

    <span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">"""</span><span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">Define self.rfile and self.wfile for datagram sockets.</span><span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">"""</span>

    <span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">def</span><span style="box-sizing: border-box; line-height: 1.5 !important"> setup(self):
      </span><span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">from</span> io <span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">import</span><span style="box-sizing: border-box; line-height: 1.5 !important"> BytesIO
      self.packet, self.socket </span>=<span style="box-sizing: border-box; line-height: 1.5 !important"> self.request
      self.rfile </span>=<span style="box-sizing: border-box; line-height: 1.5 !important"> BytesIO(self.packet)
      self.wfile </span>=<span style="box-sizing: border-box; line-height: 1.5 !important"> BytesIO()

    </span><span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">def</span><span style="box-sizing: border-box; line-height: 1.5 !important"> finish(self):
      self.socket.sendto(self.wfile.getvalue(), self.client_address)</span></pre>
</div>
</div>
<p style="box-sizing: border-box; font-family: &quot;Comic Sans MS&quot;, &quot;Microsoft YaHei&quot;, 黑体, 宋体, sans-serif; font-size: 16px !important"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif">从源码中可以看出,BaseRequestHandler中的setup()/handle()/finish()什么内容都没有定义,而他的两个派生类<span style="box-sizing: border-box">StreamRequestHandler和DatagramRequestHandler</span>则都重写了setup()/finish()。</span></p>
<p style="box-sizing: border-box; font-family: &quot;Comic Sans MS&quot;, &quot;Microsoft YaHei&quot;, 黑体, 宋体, sans-serif; font-size: 16px !important"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif">因此当我们需要自己编写socketserver程序时,只需要合理选择<span style="box-sizing: border-box">StreamRequestHandler和DatagramRequestHandler</span>之中的一个作为父类,然后自定义一个请求处理类,并在其中重写handle()方法即可。</span></p>
<p style="box-sizing: border-box; font-family: &quot;Comic Sans MS&quot;, &quot;Microsoft YaHei&quot;, 黑体, 宋体, sans-serif; font-size: 16px !important">&nbsp;</p>
<p style="box-sizing: border-box; font-family: &quot;Comic Sans MS&quot;, &quot;Microsoft YaHei&quot;, 黑体, 宋体, sans-serif; font-size: 16px !important"><strong style="box-sizing: border-box"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif">用socketserver创建一个服务的步骤:</span></strong></p>
<p style="box-sizing: border-box; font-family: &quot;Comic Sans MS&quot;, &quot;Microsoft YaHei&quot;, 黑体, 宋体, sans-serif; font-size: 16px !important"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif">1&nbsp; 创建一个request handler class(请求处理类),合理选择<span style="box-sizing: border-box"><span style="box-sizing: border-box">StreamRequestHandler和DatagramRequestHandler之中的一个作为父类(当然,使用<span style="box-sizing: border-box">BaseRequestHandler</span>作为父类也可)</span></span>,并重写它的handle()方法。<br style="box-sizing: border-box"></span></p>
<p style="box-sizing: border-box; font-family: &quot;Comic Sans MS&quot;, &quot;Microsoft YaHei&quot;, 黑体, 宋体, sans-serif; font-size: 16px !important"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif">2&nbsp; 实例化一个server class对象,并将服务的地址和之前创建的request handler class传递给它。</span></p>
<p style="box-sizing: border-box; font-family: &quot;Comic Sans MS&quot;, &quot;Microsoft YaHei&quot;, 黑体, 宋体, sans-serif; font-size: 16px !important"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif">3&nbsp; 调用server class对象的handle_request() 或 serve_forever()方法来开始处理请求。</span></p>
<p style="box-sizing: border-box; color: rgba(85, 85, 85, 1); font-size: 13.6364px; margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0; clear: both; height: auto; overflow: hidden; font-family: 宋体, &quot;Arial Narrow&quot;, arial, serif; line-height: 25.4545px">&nbsp;<span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif; font-size: 16px"><span style="box-sizing: border-box; color: rgba(0, 0, 0, 1)"><strong style="box-sizing: border-box">代码实例</strong></span>:</span></p>
<div class="cnblogs_code" style="box-sizing: border-box">
<div id="cnblogs_code_open_0daf0c24-87ff-4f2d-afe5-b30248513f6e" class="cnblogs_code_hide" style="box-sizing: border-box; display: block">
<pre><span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">import</span><span style="box-sizing: border-box; line-height: 1.5 !important"> socketserver

</span><span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">class</span><span style="box-sizing: border-box; line-height: 1.5 !important"> MyTCPHandler(socketserver.BaseRequestHandler):
    </span><span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">"""</span><span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">
    The request handler class for our server.

    It is instantiated once per connection to the server, and must
    override the handle() method to implement communication to the
    client.
    </span><span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">"""</span>

    <span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">def</span><span style="box-sizing: border-box; line-height: 1.5 !important"> handle(self):
      </span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important"> self.request is the TCP socket connected to the client</span>
      self.data = self.request.recv(1024<span style="box-sizing: border-box; line-height: 1.5 !important">).strip()
      </span><span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">print</span>(<span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">"</span><span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">{} wrote:</span><span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">"</span><span style="box-sizing: border-box; line-height: 1.5 !important">.format(self.client_address))
      </span><span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">print</span><span style="box-sizing: border-box; line-height: 1.5 !important">(self.data)
      </span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important"> just send back the same data, but upper-cased</span>
<span style="box-sizing: border-box; line-height: 1.5 !important">      self.request.sendall(self.data.upper())

</span><span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">if</span> <span style="box-sizing: border-box; color: rgba(128, 0, 128, 1); line-height: 1.5 !important">__name__</span> == <span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">"</span><span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">__main__</span><span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">"</span><span style="box-sizing: border-box; line-height: 1.5 !important">:
    HOST, PORT </span>= <span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">"</span><span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">localhost</span><span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">"</span>, 9999

    <span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important"> Create the server, binding to localhost on port 9999</span>
    server =<span style="box-sizing: border-box; line-height: 1.5 !important"> socketserver.TCPServer((HOST, PORT), MyTCPHandler)

    </span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important"> Activate the server; this will keep running until you</span>
    <span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important"> interrupt the program with Ctrl-C</span>
    server.serve_forever()</pre>
</div>
</div>
<div class="cnblogs_code" style="box-sizing: border-box">
<div id="cnblogs_code_open_59c76a2a-b55c-43e3-82ea-7f74b65a6295" class="cnblogs_code_hide" style="box-sizing: border-box; display: block">
<pre><span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">import</span><span style="box-sizing: border-box; line-height: 1.5 !important"> socket
</span><span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">import</span><span style="box-sizing: border-box; line-height: 1.5 !important"> sys

HOST, PORT </span>= <span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">"</span><span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">localhost</span><span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">"</span>, 9999<span style="box-sizing: border-box; line-height: 1.5 !important">
data </span>= <span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">"</span> <span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">"</span>.join(sys.argv)

</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important"> Create a socket (SOCK_STREAM means a TCP socket)</span>
sock =<span style="box-sizing: border-box; line-height: 1.5 !important"> socket.socket(socket.AF_INET, socket.SOCK_STREAM)

</span><span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">try</span><span style="box-sizing: border-box; line-height: 1.5 !important">:
    </span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important"> Connect to server and send data</span>
<span style="box-sizing: border-box; line-height: 1.5 !important">    sock.connect((HOST, PORT))
    sock.sendall(bytes(data </span>+ <span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">"</span><span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">\n</span><span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">"</span>, <span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">"</span><span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">utf-8</span><span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">"</span><span style="box-sizing: border-box; line-height: 1.5 !important">))

    </span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important">#</span><span style="box-sizing: border-box; color: rgba(0, 128, 0, 1); line-height: 1.5 !important"> Receive data from the server and shut down</span>
    received = str(sock.recv(1024), <span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">"</span><span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">utf-8</span><span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">"</span><span style="box-sizing: border-box; line-height: 1.5 !important">)
</span><span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">finally</span><span style="box-sizing: border-box; line-height: 1.5 !important">:
    sock.close()

</span><span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">print</span>(<span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">"</span><span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">Sent:   {}</span><span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">"</span><span style="box-sizing: border-box; line-height: 1.5 !important">.format(data))
</span><span style="box-sizing: border-box; color: rgba(0, 0, 255, 1); line-height: 1.5 !important">print</span>(<span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">"</span><span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">Received: {}</span><span style="box-sizing: border-box; color: rgba(128, 0, 0, 1); line-height: 1.5 !important">"</span>.format(received))</pre>
</div>
</div>
<div id="cnblogs_post_body" class="blogpost-body " style="box-sizing: border-box; margin-bottom: 20px; color: rgba(75, 75, 75, 1); font-family: &quot;Comic Sans MS&quot;, &quot;Microsoft YaHei&quot;, 黑体, 宋体, sans-serif; font-size: 13px">
<p style="box-sizing: border-box; color: rgba(0, 0, 0, 1); font-size: 16px !important"><strong style="box-sizing: border-box"><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif; font-size: 14pt">转载:</span></strong><span style="box-sizing: border-box; font-family: &quot;comic sans ms&quot;, sans-serif; font-size: 14pt">https://www.cnblogs.com/MnCu8261/p/5546823.html</span></p>
</div><br><br>
来源:https://www.cnblogs.com/hls91/p/11714827.html
頁: [1]
查看完整版本: python基础之socket与socketserver