欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

day8--socketserver

发布时间:2025/4/16 编程问答 32 豆豆
生活随笔 收集整理的这篇文章主要介绍了 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 socketserverclass MyTCPHandler(socketserver.BaseRequestHandler):'''创建一个socketserver服务器接收端,首先实例化一个类'''def handle(self):self.data = self.request.recv(1024).strip() #接收客户端发送的消息print("IP:%s,端口:%s链接进来了!!!" %(self.client_address[0],self.client_address[1]))'''打印那个客户端端口连接过来了'''print(self.data.decode('utf-8')) #打印接收到的消息self.request.send(self.data.upper()) #把接收到的消息大写返回回去if __name__ == "__main__":HOST,PORT = 'localhost',9999server = socketserver.TCPServer((HOST,PORT),MyTCPHandler)'''创建连接实例'''server.serve_forever()

    上面代码中,我们创建了socketserver实例的服务器端,其实原理与socket都是一样的,不同的是,socketserver是对服务器端连接的封装,如个别bind()、listen()、accept()的封装,我们只需要self.request.recv(length).strip()接收数据即可,不用关心太多底层的问题,让创建socket的过程变得简单。

    socket创建的客户端:

'''创建一个socketserver客户端,客户端与socket客户端是完全一样的,只是服务器端不一样而已''' import socketclient = socket.socket() client.connect(("localhost",9999)) while True:mess = input("请输入您要发送的数据>>:")client.send(mess.encode('utf-8')) #客户端发送数据给服务器端data = client.recv(1024) #客户端接收服务器发送过来的数据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 socketserverclass MyTCPHandler(socketserver.BaseRequestHandler):'''创建一个socketserver服务器接收端,首先实例化一个类'''def handle(self):while True:self.data = self.request.recv(1024).strip() #接收客户端发送的消息if not self.data:'''如果接收的为空,说明服务器端发送的是空的数据,或者是服务器端断开了'''print(self.client_address,"客户端断开了!!!")breakprint("IP:%s,端口:%s链接进来了!!!" %(self.client_address[0],self.client_address[1]))'''打印那个客户端端口连接过来了'''print(self.data.decode('utf-8')) #打印接收到的消息self.request.send(self.data.upper()) #把接收到的消息大写返回回去if __name__ == "__main__":HOST,PORT = 'localhost',9997server = socketserver.TCPServer((HOST,PORT),MyTCPHandler)'''创建连接实例'''server.serve_forever()

    上面代码中,对服务器进行了修改,让服务器能够循环接收数据,这样客户端就能无限发送和接收数据了,不过要牢记一点,客户端是不能够发送空的消息给服务器的,如果发送空的消息给服务器,就会卡主,传递不了消息,因而要设定发送空消息的指令。

    上面代码修改了,能够实现交互,但是我们发现了一个问题,服务器还是只能每次跟一个客户端交互,不能同时跟多个客户端交互,其他客户端必须等待本次交互完成之后,在进行交互,这与socket写的服务器和客户端没有区别,如何用socketserver实现多并发呢,下面有两种方式,一种是多线程,如下:

    (1)多线程

'''使用socketserver创建客户端''' import socketserverclass MyTCPHandler(socketserver.BaseRequestHandler):'''创建一个socketserver服务器接收端,首先实例化一个类'''def handle(self):while True:self.data = self.request.recv(1024).strip() #接收客户端发送的消息if not self.data:'''如果接收的为空,说明服务器端发送的是空的数据,或者是服务器端断开了'''print(self.client_address,"客户端断开了!!!")breakprint("IP:%s,端口:%s链接进来了!!!" %(self.client_address[0],self.client_address[1]))'''打印那个客户端端口连接过来了'''print(self.data.decode('utf-8')) #打印接收到的消息self.request.send(self.data.upper()) #把接收到的消息大写返回回去if __name__ == "__main__":HOST,PORT = 'localhost',9997server = 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 socketserverclass MyTCPHandler(socketserver.BaseRequestHandler):'''创建一个socketserver服务器接收端,首先实例化一个类'''def handle(self):while True:self.data = self.request.recv(1024).strip() #接收客户端发送的消息if not self.data:'''如果接收的为空,说明服务器端发送的是空的数据,或者是服务器端断开了'''print(self.client_address,"客户端断开了!!!")breakprint("IP:%s,端口:%s链接进来了!!!" %(self.client_address[0],self.client_address[1]))'''打印那个客户端端口连接过来了'''print(self.data.decode('utf-8')) #打印接收到的消息self.request.send(self.data.upper()) #把接收到的消息大写返回回去if __name__ == "__main__":HOST,PORT = 'localhost',9997server = 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 socketserverclass MyTCPHandler(socketserver.BaseRequestHandler):""" The request handler class for our server.It is instantiated once per connection to the server, and mustoverride the handle() method to implement communication to theclient.""" def handle(self):# self.request is the TCP socket connected to the clientself.data = self.request.recv(1024).strip()print("{} wrote:".format(self.client_address[0]))print(self.data)# just send back the same data, but upper-casedself.request.sendall(self.data.upper())if __name__ == "__main__":HOST, PORT = "localhost", 9999# Create the server, binding to localhost on port 9999server = socketserver.TCPServer((HOST, PORT), MyTCPHandler)# Activate the server; this will keep running until you# interrupt the program with Ctrl-Cserver.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()的封装。

转载于:https://www.cnblogs.com/gengcx/p/7407256.html

总结

以上是生活随笔为你收集整理的day8--socketserver的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。