专栏首页python3Python32 Socket Serv

Python32 Socket Serv

类型

  • socketserver有几种类型: class socketserver.TCPServer:用于TCP class socketserver.UDPServer:用于UDP class socketserver.UnixStreamServer:用于Unix的TCP class socketserver.UnixDatagramServer:用于Unix的UDP

TCPServer继承了BaseServer UnixStreamServer继承了TCPServer

  • 创建socket server至少分以下几步: 1、必须创建一个请求处理类,并且这个类要继承BaseRequestHandler,还要重写父类里的handle方法(跟客户端所有的交互都是在handle中写的)。 2、必须要实例化一个协议server(如TCPServer),并且传递server ip和你上面创建的请求处理类,给这个TCPServer(实例化的时候将IP和请求处理类传给TCPServer)。 3、然后可以根据上面的实例来处理请求: server.handle_request() #只处理一个请求 server.handle_forever() #处理多个请求,永远执行(一般都是用这个) 4、调用server_close()去关闭
server端:

import socketserver

class MyTCPHandler(socketserver.BaseRequestHandler):
    '''第1步:创建处理类,继承Base。 客户端每一次请求过来都会实例化这个类'''

    def handle(self):
        '''第1步:重写handle方法,handle默认存在父类中代码是空的。 客户端所有交互都在handle中完成'''

        while True: #使其可以循环发送数据
            self.data = self.request.recv(1024).decode().strip()
            #这里的self.request.recv相当于之前用的conn.recv

            print ("{} wrote:".format(self.client_address[0]))
            #打印客户端的IP地址信息

            print (self.data)
            #打印数据信息

            self.request.send(self.data.upper().encode('utf-8'))
            #传回数据给客户端,只是upper了一下
            #sendall就是重复调用send

if __name__ == "__main__":
    HOST,PORT = "localhost",9999

    server = socketserver.TCPServer((HOST,PORT),MyTCPHandler)
    #第2步:实例化TCPServer,并将IP和MyTCPHandler当做参数传给请求处理类
    #监听客户端的每一个请求,就会实例化MyTCPHandler这个类,拿MyTCPHandler的handle与客户端交互。

    server.serve_forever()
    #第3步:允许永远处理多个请求

client端:

import socket

client = socket.socket()
client.connect(('localhost',9999))

while True:

    msg = input(">>:").strip()
    if len(msg) == 0:continue
    client.send(msg.encode('utf-8'))
    data = client.recv(1024)
    print ("recv:",data.decode())

client.close()

client执行结果:
>>:abc
recv: ABC
>>:efg
recv: EFG
>>:hhh
recv: HHH
>>:

server执行结果:
127.0.0.1 wrote:
abc
127.0.0.1 wrote:
efg
127.0.0.1 wrote:
hhh

client断开后server报错:
----------------------------------------
Exception happened during processing of request from ('127.0.0.1', 53933)
Traceback (most recent call last):
  File "D:\python37\lib\socketserver.py", line 313, in _handle_request_noblock
    self.process_request(request, client_address)
  File "D:\python37\lib\socketserver.py", line 344, in process_request
    self.finish_request(request, client_address)
  File "D:\python37\lib\socketserver.py", line 357, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "D:\python37\lib\socketserver.py", line 712, in __init__
    self.handle()
  File "E:/python/代码练习/A2.py", line 11, in handle
    self.data = self.request.recv(1024).decode().strip()
ConnectionResetError: [WinError 10054] 远程主机强迫关闭了一个现有的连接。
----------------------------------------
#可以看到这里报错ConnectionResetError: [WinError 10054]
修改server端:
import socketserver

class MyTCPHandler(socketserver.BaseRequestHandler):

    def handle(self):

        while True: #使其可以循环发送数据
           try: #使用try的话就不需要使用 if not data的方式来判断客户端断开时,无数据的情况了
                self.data = self.request.recv(1024).decode().strip()
                #这里的self.request.recv相当于之前用的conn.recv

                print ("{} wrote:".format(self.client_address[0]))

                print (self.data)

                self.request.send(self.data.upper().encode('utf-8'))
           except ConnectionResetError as e:
               print ("err:",e)
               break    #这里一定要break,不然就会一直死循环

if __name__ == "__main__":
    HOST,PORT = "localhost",9999

    server = socketserver.TCPServer((HOST,PORT),MyTCPHandler)

    server.serve_forever()

server执行结果:
127.0.0.1 wrote:
abc
127.0.0.1 wrote:
123
err: [WinError 10054] 远程主机强迫关闭了一个现有的连接。
#客户端断开连接后,就通过断言的方式抓到错误了。

上面的代码目前还不能支持多并发,如果有多个并发,后面的并发就会被挂起; 如果要并发的话,需要修改一下代码。

通过ctrl点TCPServer

可以看到TCPServer是继承了BaseServer

修改server端:

import socketserver

class MyTCPHandler(socketserver.BaseRequestHandler):

    def handle(self):

        while True: #使其可以循环发送数据
           try: #使用try的话就不需要使用 if not data的方式来判断客户端断开时,无数据的情况了
                self.data = self.request.recv(1024).decode().strip()

                print ("{} wrote:".format(self.client_address[0]))

                print (self.data)

                self.request.send(self.data.upper().encode('utf-8'))

           except ConnectionResetError as e:
               print ("err:",e)
               break    
if __name__ == "__main__":
    HOST,PORT = "localhost",9999

    server = socketserver.ThreadingTCPServer((HOST,PORT),MyTCPHandler)
    # 上面的代码需要使用ThreadingTCPServer

    server.serve_forever()

client 1执行结果:
>>:test 1
recv: TEST 1
>>:

client 2执行结果:
>>:test 2
recv: TEST 2
>>:

client 3执行结果:
>>:test 3
recv: TEST 3
>>:

server 执行结果:
127.0.0.1 wrote:
test 1
127.0.0.1 wrote:
test 2
127.0.0.1 wrote:
test 3

可以看到server端现在支持多并发,没有被挂起;每来一个请求会开启一个新线程与server交互;每个线程都是独立的,10个线程,就可以做10件事情。

通过ctrl点ThreadingTCPServer

可以看到将TCPServer这个类传了进去 同时还传了ThreadingMixIn;TCPServer是负责与客户端交互,而多线程都是由ThreadingMixIn实现的。

ctrl点ThreadingMixIn

这部分就是多线程的主要代码

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • socketserver实现并发

    TCP协议的socket一次只能和一个客户端通信, 而socketsever可以时间和多个客户端通信.

    py3study
  • Python 学习笔记 - socket

    前面学习的例子都是单线程的socket收发;如果有多个用户同时接入,那么除了第一个连入的,后面的都会处于挂起等待的状态,直到当前连接的客户端断开为止。

    py3study
  • wsgi 协议

    本来没打算这么早就学习 wsgi 的,因为想要学习python 是如何处理网络请求的绕不开 wsgi,所以只好先学习一下 wsgi。先对 wsgi 有个印象,到...

    py3study
  • socketserver实现并发

    TCP协议的socket一次只能和一个客户端通信, 而socketsever可以时间和多个客户端通信.

    py3study
  • Python 学习笔记 - socket

    前面学习的例子都是单线程的socket收发;如果有多个用户同时接入,那么除了第一个连入的,后面的都会处于挂起等待的状态,直到当前连接的客户端断开为止。

    py3study
  • mqtt 客户端 基于Python

    这几天一直在搞安全通信,微信小程序,反向代理等等,为了能让自己对整个系统做到把控,主要是需要了解每一个细节的地方,所以今天花了3个小时的时间学习了Python,...

    杨奉武
  • Python爬虫基础知识:百度贴吧网络爬虫及源码分享

    糖豆贴心提醒,本文阅读时间6分钟 百度贴吧的爬虫制作和糗百的爬虫制作原理基本相同,都是通过查看源码扣出关键数据,然后将其存储到本地txt文件。 项目内容: ...

    小小科
  • [转]红黑树

    先来看下算法导论对R-B Tree的介绍: 红黑树,一种二叉查找树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black。 通过对任何一条从根到...

    DH镔
  • Okhttp3源码解析(3)-Call分析(整体流程)

    想起来了吧?无论是get还是post请求 都要生成call对象,在上面我们发现call实例需要一个okHttpClient与request实例 ,我们先点进C...

    秦子帅
  • [iOS] 输入框高度随输入内容变化

    对于第一点,有一个方便的计算方法,就是获取UITextView内容的高度比上UITextView的字体的高度,即可得到当前的行数。

    wOw

扫码关注云+社区

领取腾讯云代金券