033.基于UDP的套接字通信、基于socketserver实现并发编程

一、基于UDP的套接字通信

(一)TCP与UDP协议的对比

1.可靠性

(1)TCP协议是可靠协议

​ 对方必须回复一个ack确认消息,才会将自己这端的数据从内存中删除。

(2)UDP是不可靠协议

​ 发送一条消息就会立即删除,不管对方是否接收到。

2.有无链接

​ tcp有链接,udp无链接。

3.传输数据的效率

​ udp更高。

4.粘包问题

​ udp协议称之为数据包协议,每次发送都是一个完整的数据报,一个发送唯一对应一个接收,所以udp没有粘包问题。

(二)基于UDP的套接字基本模板

​ udp是无链接的,先启动哪一端都不会报错。

1.udp服务端

ss = socket()   #创建一个服务器的套接字
ss.bind()       #绑定服务器套接字
inf_loop:       #服务器无限循环
    cs = ss.recvfrom()/ss.sendto() # 对话(接收与发送)
ss.close()                         # 关闭服务器套接字

2.udp客户端

cs = socket()   # 创建客户套接字
comm_loop:      # 通讯循环
    cs.sendto()/cs.recvfrom()   # 对话(发送/接收)
cs.close()                      # 关闭客户套接字

(三)UDP套接字简单示例

1.udp服务端

# UDP协议基本的服务端
from socket import *
import time

server = socket(AF_INET, SOCK_DGRAM)
server.bind(('127.0.0.1',8080))

while True:
    data, client_addr = server.recvfrom(1024)
    time.sleep(1)
    server.sendto(data.upper(), client_addr)

2.udp客户端

# UDP协议基本的客户端
from socket import *

client = socket(AF_INET, SOCK_DGRAM)

while True:
    msg = input('>>>:').strip()
    client.sendto(msg.encode('utf-8'), ('127.0.0.1', 8080))

    data, server_addr = client.recvfrom(1024)
    print(data.decode('utf-8'))

二、基于socketserver实现并发编程

​ 基于TCP的套接字循环,关键就是两个循环,一个链接循环,一个通信循环。

(一)socketserver模块的两大类:

1.server类

​ 用于解决链接循环问题。

2.request类

​ 用于解决通信循环问题。

(二)使用socketserver实现基于TCP的并发

1.TCP并发服务端

# TCP--server端------------
import socketserver


class MyRequestHandler(socketserver.BaseRequestHandler):
    def handle(self):
        print(self.client_address)
        while True:
            try:
                data = self.request.recv(1024)

                if len(data) == 0: break
                self.request.send(data.upper())
            except Exception:
                break
        self.request.close()


if __name__ == '__main__':
    s = socketserver.ThreadingTCPServer(('127.0.0.1', 8080), MyRequestHandler, bind_and_activate=True)
    s.serve_forever()

2.TCP并发客户端

# TCP--client端------------
from socket import *

client = socket(AF_INET, SOCK_STREAM)
client.connect(('127.0.0.1', 8080))

while True:
    msg = input('>>>:').strip()
    if len(msg) == 0:
        continue

    client.send(msg.encode('utf-8'))
    data = client.recv(1024)
    print(data.decode('utf-8'))

(三)使用socketserver实现基于UDP的并发

1.UDP并发服务端

# UDP--server端------------
import socketserver


class MyRequestHandler(socketserver.BaseRequestHandler):
    def handle(self):
        data, server = self.request
        server.sendto(data.upper(), self.client_address)


if __name__ == '__main__':
    s = socketserver.ThreadingUDPServer(('127.0.0.1', 8080), MyRequestHandler, bind_and_activate=True)
    s.serve_forever()

2.UDP并发客户端

# UDP--client端------------
from socket import *

client = socket(AF_INET, SOCK_DGRAM)

while True:
    msg = input('>>>:').strip()
    client.sendto(msg.encode('utf-8'), ('127.0.0.1', 8080))

    data, server_addr = client.recvfrom(1024)
    print(data.decode('utf-8'))

(四)分析总结

1.基于tcp的socketserver我们自己定义的类中的

(1)self.server即套接字对象

(2)self.request即一个链接

(3)self.client_address即客户端地址

2.基于udp的socketserver我们自己定义的类中的

(1)self.request是一个元组(第一个元素是客户端发来的数据,第二部分是服务端的udp套接字对象),

​ 如:(b’adsf’, <socket.socket fd=200, family=AddressFamily.AF_INET, type=SocketKind.SOCK_DGRAM, proto=0, laddr=(‘127.0.0.1’, 8080)>)

(2)self.client_address即客户端地址

(1)self.request是一个元组(第一个元素是客户端发来的数据,第二部分是服务端的udp套接字对象),

​ 如:(b’adsf’, <socket.socket fd=200, family=AddressFamily.AF_INET, type=SocketKind.SOCK_DGRAM, proto=0, laddr=(‘127.0.0.1’, 8080)>)

(2)self.client_address即客户端地址

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值