UDP套接字通信、socketserver并发编程
UDP套接字通信、socketserver并发编程
一 基于UDP的套接字通信
1 TCP与UDP协议的对比
### 1.可靠性
#### (1) TCP协议是可靠协议
		对方必须回复一个ack确认消息,才会将自己这端的数据从内存中删除。
#### (2) UDP是不可靠协议
		发送一条消息就会立即删除,不管对方是否接收到。
### 2.有无链接
		tcp有链接,udp无链接。
### 3.传输数据的效率
		udp更高。
### 4.粘包问题
		udp协议称之为数据包协议,每次发送都是一个完整的数据报,一个发送唯一对应一个接收,所以udp没有粘包问题。
2 基于UDP的套接字基本模板
 udp是无链接的,先启动哪一端都不会报错。
2.1 udp服务端
ss = socket()   #创建一个服务器的套接字
ss.bind()       #绑定服务器套接字
inf_loop:       #服务器无限循环
    cs = ss.recvfrom()/ss.sendto() # 对话(接收与发送)
ss.close()                         # 关闭服务器套接字
2.2 udp客户端
cs = socket()   # 创建客户套接字
comm_loop:      # 通讯循环
    cs.sendto()/cs.recvfrom()   # 对话(发送/接收)
cs.close()                      # 关闭客户套接字
3 UDP套接字简单示例
3.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)
3.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的套接字循环,关键就是两个循环,一个链接循环,一个通信循环。
1 socketserver模块的两大类:
### 1.server类
	用于解决链接循环问题。
### 2.request类
	用于解决通信循环问题。
2 使用socketserver实现基于TCP的并发
2.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.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'))
3 使用socketserver实现基于UDP的并发
3.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()
3.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'))
4 分析总结
4.1 基于tcp的socketserver我们自己定义的类中的
(1) self.server即套接字对象
(2) self.request即一个链接
(3) self.client_address即客户端地址
4.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即客户端地址
 
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号