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地址和端口号,再指定协议类型 ...
随机推荐
- (五)bootloader 启动 ucore os
Lab1 : bootloader 启动 ucore os 一.内容提要 x86启动顺序 C函数调用 gcc内联汇编(inline assembly) x86-32下的中断处理 小结 二.x86启动顺 ...
- sock_ntop.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <netinet/in ...
- 我的Mac中毒了,病毒居然叫做MacPerformance
禁用 ReportCrash 直接干掉进程肯定不管用,从名字就知道这个进程会自动被触发,除非修改系统配置. Google 了一下,发现很简单,在 terminal 里执行 launchctl unlo ...
- Java SE之 Eclipse错误: 找不到或无法加载主类或项目无法编译10种解决大法!【摘抄】
声明一下:此BUG确实经常困扰我许久,今日遇到很强大的一套解决办法,又怕原博主的网页以后查找不到,故此摘抄copy一份,望得各方侵权一事而谅解. 传送门先行送上:http://blog.csdn.ne ...
- weblogic中部署SSH项目遇到的坑
总结将SSH项目部署到weblogic遇到的坑.项目中是SSH,另外还用到了webservice.quartz等框架.在tomcat部署是可以的,现在总结部署到weblogic遇到的坑. 在这里说一下 ...
- 【转】Shell编程进阶篇(完结)
[转]Shell编程进阶篇(完结) 1.1 for循环语句 在计算机科学中,for循环(英语:for loop)是一种编程语言的迭代陈述,能够让程式码反复的执行. 它跟其他的循环,如while循环,最 ...
- Majority Element(169) && Majority Element II(229)
寻找多数元素这一问题主要运用了:Majority Vote Alogrithm(最大投票算法)1.Majority Element 1)description Given an array of si ...
- eMMC基础技术8:操作模式1-boot mode
1.前言 eMMC总线操作包含: boot mode device identification mode interrupt mode data transfer mode 本文主要描述boot m ...
- 如何读取Linux键值,输入子系统,key,dev/input/event,dev/event,C语言键盘【转】
转自:https://blog.csdn.net/lanmanck/article/details/8423669 相信各位使用嵌入式的都希望直接读取键值,特别是芯片厂家已经提供input驱动的情况下 ...
- vue中遇到的坑!!!!!
一 .vue安装的坑 报错时的常见问题 1.cnpm install 模块名 –save-dev(关于环境的,表现为npm run dev 启动不了)cnpm install 模块名 –save(关于 ...