day8--socketserver
socketserver分类:
1、TCP协议
class socketserver.TCPServer(server_address,RequestHandlerClass,bind_and_activate=True)
2、UDP协议
class socketserver.UDPServer(server_address,RequestHandlerClass,bind_and_activate=True)
剩下两种不常用协议如下:
calss socketserver.UnixStreamServer(server_address,RequestHandlerClass,bind_and_activate=True)
class socketserver.UnixDatagramServer(server_adddress,RequestHandlerClass,bind_and_activate=True)
协议之间的继承关系如下:

用socketServer创建一个服务的步骤:
1、创建一个request handler class(请求处理类),合理选择StreamRequestHandler和DatagramRequestHandler之中的一个作为父类(当然,便用BaseRequestHandler作为父类也可),并重写它的handler()方法;
2、实例化一个server class对象,并将服务的地址和之前创建的request handler class传递给它;
3、调用server class对象的handle_request()或server_forver()方法来开始处理请求,server_forever()是永久处理连接,使用这一个。
handle_request()只处理一个请求,处理完一个请求之后退出;server_forever()处理多个请求。
与客户端每一个交互都是在handle()中处理的。
socketServer其实是对客户端功能的进一步封装,比如bind(),listen(),accept()功能的封装,把这些功能统一分装到socketserver中,并且能够实现多线程,多进程的多并发的情况,客户端没有变化,下面来看一个简单的例子:
socketserver写成的服务器端:
'''使用socketserver创建客户端'''
import socketserver class MyTCPHandler(socketserver.BaseRequestHandler):
'''创建一个socketserver服务器接收端,首先实例化一个类'''
def handle(self):
self.data = self.request.recv().strip() #接收客户端发送的消息
print("IP:%s,端口:%s链接进来了!!!" %(self.client_address[],self.client_address[]))
'''打印那个客户端端口连接过来了'''
print(self.data.decode('utf-8')) #打印接收到的消息
self.request.send(self.data.upper()) #把接收到的消息大写返回回去 if __name__ == "__main__":
HOST,PORT = 'localhost',
server = socketserver.TCPServer((HOST,PORT),MyTCPHandler)
'''创建连接实例'''
server.serve_forever()
上面代码中,我们创建了socketserver实例的服务器端,其实原理与socket都是一样的,不同的是,socketserver是对服务器端连接的封装,如个别bind()、listen()、accept()的封装,我们只需要self.request.recv(length).strip()接收数据即可,不用关心太多底层的问题,让创建socket的过程变得简单。
socket创建的客户端:
'''创建一个socketserver客户端,客户端与socket客户端是完全一样的,只是服务器端不一样而已'''
import socket client = socket.socket()
client.connect(("localhost",))
while True:
mess = input("请输入您要发送的数据>>:")
client.send(mess.encode('utf-8')) #客户端发送数据给服务器端
data = client.recv() #客户端接收服务器发送过来的数据
print("接收到的数据:",data.decode('utf-8'))
上面代码是socket创建的客户端,就是一个简单的收发数据,在这里能够连续发送数据,下面来首先启动服务器端,接着启动客户端进行交互。
运行如下:
请输入您要发送的数据>>:dfasfdasd
接收到的数据: DFASFDASD
请输入您要发送的数据>>:1
接收到的数据:
请输入您要发送的数据>>:das
Traceback (most recent call last):
File "/home/zhuzhu/第八天/socket_server/socketserver_client.py", line 8, in <module>
client.send(mess.encode('utf-8')) #客户端发送数据给服务器端
BrokenPipeError: [Errno 32] Broken pipe
从上面可以看出,第一次交互是没有问题的,第二次交互就开始出错了,为什么呢?我们来看下服务器端,在服务器端里面,handle()里面每次只能接收一次数据,因此会出现错误的情况,下面我们来让服务器端实现连续交互,修改服务器端,如下:
'''使用socketserver创建客户端'''
import socketserver class MyTCPHandler(socketserver.BaseRequestHandler):
'''创建一个socketserver服务器接收端,首先实例化一个类'''
def handle(self):
while True:
self.data = self.request.recv().strip() #接收客户端发送的消息
if not self.data:
'''如果接收的为空,说明服务器端发送的是空的数据,或者是服务器端断开了'''
print(self.client_address,"客户端断开了!!!")
break
print("IP:%s,端口:%s链接进来了!!!" %(self.client_address[],self.client_address[]))
'''打印那个客户端端口连接过来了'''
print(self.data.decode('utf-8')) #打印接收到的消息
self.request.send(self.data.upper()) #把接收到的消息大写返回回去 if __name__ == "__main__":
HOST,PORT = 'localhost',
server = socketserver.TCPServer((HOST,PORT),MyTCPHandler)
'''创建连接实例'''
server.serve_forever()
上面代码中,对服务器进行了修改,让服务器能够循环接收数据,这样客户端就能无限发送和接收数据了,不过要牢记一点,客户端是不能够发送空的消息给服务器的,如果发送空的消息给服务器,就会卡主,传递不了消息,因而要设定发送空消息的指令。
上面代码修改了,能够实现交互,但是我们发现了一个问题,服务器还是只能每次跟一个客户端交互,不能同时跟多个客户端交互,其他客户端必须等待本次交互完成之后,在进行交互,这与socket写的服务器和客户端没有区别,如何用socketserver实现多并发呢,下面有两种方式,一种是多线程,如下:
(1)多线程
'''使用socketserver创建客户端'''
import socketserver class MyTCPHandler(socketserver.BaseRequestHandler):
'''创建一个socketserver服务器接收端,首先实例化一个类'''
def handle(self):
while True:
self.data = self.request.recv().strip() #接收客户端发送的消息
if not self.data:
'''如果接收的为空,说明服务器端发送的是空的数据,或者是服务器端断开了'''
print(self.client_address,"客户端断开了!!!")
break
print("IP:%s,端口:%s链接进来了!!!" %(self.client_address[],self.client_address[]))
'''打印那个客户端端口连接过来了'''
print(self.data.decode('utf-8')) #打印接收到的消息
self.request.send(self.data.upper()) #把接收到的消息大写返回回去 if __name__ == "__main__":
HOST,PORT = 'localhost',
server = socketserver.ThreadingTCPServer((HOST,PORT),MyTCPHandler)
'''创建连接实例'''
server.serve_forever()
多线程就是修改server连接的方式,socketserver.ThreadingTCPServer即可,如下:
server = socketserver.ThreadingTCPServer((HOST,PORT),MyTCPHandler)
上面修改之后,就能实现多线程多并发,我们可以同时启动多个客户端进行交互。
上面启动一个服务器,多个客户端,交互如下:
客户端1:
请输入您要发送的数据>>:这么神奇
接收到的数据: 这么神奇
客户端2:
请输入您要发送的数据>>:alex
接收到的数据: ALEX
客户端3:
请输入您要发送的数据>>:sb
接收到的数据: SB
客户端4:
请输入您要发送的数据>>:yes
接收到的数据: YES
服务器:
IP:127.0.0.1,端口:54856链接进来了!!!
这么神奇
IP:127.0.0.1,端口:54858链接进来了!!!
alex
IP:127.0.0.1,端口:54860链接进来了!!!
sb
IP:127.0.0.1,端口:54862链接进来了!!!
yes
上面可以看出,我们实现了多线程多并发的交互,我们也可以实现多进程的交互。
(2)多进程
多进程和多线程是一样的,也是修改服务器端的交互指令即可,如下:
server = socketserver.ForkingTCPServer((HOST,PORT),MyTCPHandler)
上面,ForKingTCPServer((IP,端口号),实例化的类),就实现了和多线程一个的多并发情况,如下:
'''使用socketserver创建客户端'''
import socketserver class MyTCPHandler(socketserver.BaseRequestHandler):
'''创建一个socketserver服务器接收端,首先实例化一个类'''
def handle(self):
while True:
self.data = self.request.recv().strip() #接收客户端发送的消息
if not self.data:
'''如果接收的为空,说明服务器端发送的是空的数据,或者是服务器端断开了'''
print(self.client_address,"客户端断开了!!!")
break
print("IP:%s,端口:%s链接进来了!!!" %(self.client_address[],self.client_address[]))
'''打印那个客户端端口连接过来了'''
print(self.data.decode('utf-8')) #打印接收到的消息
self.request.send(self.data.upper()) #把接收到的消息大写返回回去 if __name__ == "__main__":
HOST,PORT = 'localhost',
server = socketserver.ForkingTCPServer((HOST,PORT),MyTCPHandler)
'''创建连接实例'''
server.serve_forever()
交互如下:
客户端1:
请输入您要发送的数据>>:dfasfdas
接收到的数据: DFASFDAS
客户端2:
请输入您要发送的数据>>:xiaozhuzhu
接收到的数据: XIAOZHUZHU
客户端3:
请输入您要发送的数据>>:pangshini
接收到的数据: PANGSHINI
客户端4:
请输入您要发送的数据>>:dapagnzhi
接收到的数据: DAPAGNZHI
服务器:
IP:127.0.0.1,端口:54876链接进来了!!!
dfasfdas
IP:127.0.0.1,端口:54878链接进来了!!!
xiaozhuzhu
IP:127.0.0.1,端口:54880链接进来了!!!
pangshini
IP:127.0.0.1,端口:54886链接进来了!!!
dapagnzhi
上面就是多进程下的多并发的交互情况,和多线程交互结果是一致的,不同的是,ForKingTCPServer()多进程在Windows下会报错,由于Windows多进程和Linux多进程的原理是不一样的。在Linux下没有问题,在Windows下会报错。
基本的socketserver代码:
import socketserver class MyTCPHandler(socketserver.BaseRequestHandler):
"""
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.
"""
def handle(self):
# self.request is the TCP socket connected to the client
self.data = self.request.recv().strip()
print("{} wrote:".format(self.client_address[]))
print(self.data)
# just send back the same data, but upper-cased
self.request.sendall(self.data.upper()) if __name__ == "__main__":
HOST, PORT = "localhost", # Create the server, binding to localhost on port
server = socketserver.TCPServer((HOST, PORT), MyTCPHandler) # Activate the server; this will keep running until you
# interrupt the program with Ctrl-C
server.serve_forever()
总结:
(1)socketserver与socket是一样的,都是为了实现客户端和服务器端的交互;
(2)socketserver能够实现多并发,而socket只能一对一的进行交互;
(3)socketserver.TCPServer是实现与socket一样的一对一交互,socketserver.ThreadingTCPServer是实现多线程下的多并发,socketserver.ForkingTCPServer是实现多进程的下的多并发的数据交互,都是在TCP协议下进行交互的,常用的还有UDP协议。
(4)客户端不能发送空的消息,服务器端也不能接收空的消息;
(5)如果服务器端接收的消息为空,说明客户端已经退出了,不然若客户端发送为空,则造成堵塞;
(6)socketserver是对socket中bind,listen,accept()的封装。
day8--socketserver的更多相关文章
- python2.0 s12 day8 _ socketserver学习
Socket 概念 一个socket就是一个点对点的链接.当今,大多数的通信都是基于Internet Protocl,因此大多数的网络Socket都是Internet Protocl(互联网)的通信( ...
- Python之路,Day8 - Socket编程进阶
Python之路,Day8 - Socket编程进阶 本节内容: Socket语法及相关 SocketServer实现多并发 Socket语法及相关 socket概念 socket本质上就是在2台 ...
- Day8 - Python网络编程 Socket编程
Python之路,Day8 - Socket编程进阶 本节内容: Socket语法及相关 SocketServer实现多并发 Socket语法及相关 socket概念 socket本质上就是在2台 ...
- Python 第八篇:异常处理、Socket语法、SocketServer实现多并发、进程和线程、线程锁、GIL、Event、信号量、进程间通讯
本节内容: 异常处理.Socket语法.SocketServer实现多并发.进程和线程.线程锁.GIL.Event.信号量.进程间通讯.生产者消费者模型.队列Queue.multiprocess实例 ...
- Python(七)Socket编程、IO多路复用、SocketServer
本章内容: Socket IO多路复用(select) SocketServer 模块(ThreadingTCPServer源码剖析) Socket socket通常也称作"套接字" ...
- 开发socketserver 以及定制开发自己的FTP服务器
socket server 示例 #服务端程序 import socketserver class TcpHandler(socketserver.BaseRequestHandler): def h ...
- SocketServer
SocketServer是基于socket写成的一个更强大的模块. SocketServer简化了网络服务器的编写.它有4个类:TCPServer,UDPServer,UnixStreamServer ...
- day8
作业要求: 1.用socket写一个 ftp服务端与客户端 2.支持get put命令 作业下载地址:ftp://www.wudonghang.com/oldboy/day8.zip ...
- Python之路,Day8 - Python基础 面向对象高级进阶与socket基础
类的成员 类的成员可以分为三大类:字段.方法和属性 注:所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多少对象,在内存中就有多少个普通字段.而其他的成员,则都是保存在类中,即:无论对象的 ...
- Python Day8
Socket Socket是网络编程的一个抽象概念.通常我们用一个Socket表示"打开了一个网络链接",而打开一个Socket需要知道目标计算机的IP地址和端口号,再指定协议类型 ...
随机推荐
- 关于Linux 虚拟机如何才能ping 通外网
需要虚拟机能够联网.以前都是用桥接模式让虚拟机跟主机通信,这几天查了好多资料,都没有写得很详细,自己捣鼓了很久,把步骤写下来吧. 虚拟机操作步骤: 点击虚拟机的“菜单栏”上的“编辑”,再点击“虚拟网络 ...
- centos6 python 安装 sqlite 解决 No module named ‘_sqlite3′
原文连接: http://blog.csdn.net/jaket5219999/article/details/53512071 系统red hat6.7 也即centos6.7 python3.5. ...
- Python 爬虫学习
#coding:utf-8 #author:Blood_Zero ''' 1.获取网页信息 2.解决编码问题,通过charset库(默认不安装这个库文件) ''' import urllib impo ...
- sqlplus连接远程数据库
方式一:简易连接,不用进行网络配置,其实就是tnsname.ora文件 命令:sqlplus 用户名/密码@ip地址[:端口]/service_name [as sysdba] 示例:sqlplus ...
- IIS配置过程中的常见问题
解析Json需要设置Mime IIS6.0 1.打开IIS添加Mime项 关联扩展名:*.json内容类型(MIME):application/x-JavaScript 2.添加映射: 位置 ...
- dump_stack的简单使用 【转】
转自:http://blog.chinaunix.net/uid-26403844-id-3361770.html http://blog.csdn.net/ryfjx6/article/detail ...
- PHP查看编译参数
PHP查看编译参数 [root@test ~]# php -i|grep configure Configure Command => './configure' '--prefix=/usr/ ...
- C++11 并发指南一(C++11 多线程初探)
引言 C++11 自2011年发布以来已经快两年了,之前一直没怎么关注,直到最近几个月才看了一些 C++11 的新特性,今后几篇博客我都会写一些关于 C++11 的特性,算是记录一下自己学到的东西吧, ...
- Windows10 + Visual Studio 2017 + CMake +OpenCV编译、开发环境配置及测试
由于最近需要使用OpenCV,本人需要在自己的PC上使用OpenCV,因此最近一直在研究如何使用Visual Studio编译OpenCV源代码并搭建开发环境,折腾了很长时间,查阅了很多相关资料,终于 ...
- mysql语句判断是否存在记录,没有则插入新纪录否则不执行
1 前言 由于项目需要,当某个表如果有记录,就不执行加入语句,否则加入新纪录(测试数据).思路是:判断表的记录是否为空,然后再决定是否插入 2 代码 DROP PROCEDURE IF EXISTS ...