基于UDP协议的套接字与SocketServer

UDP协议

UDP协议,即用户数据报协议(User Datagram Protocol),是一个简单的面向数据报的传输层协议。UDP协议只在IP数据报服务商增加了很少一点的功能,就是复用和分用,以及差错检测的功能。

基于UDP协议的Socket

1.udp协议客户端允许发空
2.udp协议不会粘包
3.udp协议服务端不存在的情况下,客户端照样不会报错
4.udp协议支持并发

UDP叫数据报协议,意味着发消息都带有数据报头
UDP的server不需要就行监听也不需要建立连接
在启动服务之后只能被动的等待客户端发送消息过来,客户端发送消息的时候,要带上服务端的地址
服务端在回复消息的时候,也需要带上客户端的地址

1.服务端

import socket

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

msg, addr = server.recvfrom(1024)
print(msg.decode('utf-8'))
server.sendto(b'hello', addr)

server.close()

2.客户端

import socket

client = socket.socket(type=socket.SOCK_DGRAM)
server_addr = ('127.0.0.1', 8080)

client.sendto(b'hello baby!', server_addr)
msg, addr = client.recvfrom(1024)
print(msg, addr)

udp特点:
无链接,类似于发短信,发了就行对方爱回不回,没有任何关系。将服务端关了,客户端起起来照样能够发数据。因为不需要考虑服务端能不能收到

验证udp协议有无粘包问题

import socket
server = socket.socket(type=socket.SOCK_DGRAM)
server.bind(('127.0.0.1',8080))
print(server.recvfrom(1024))
print(server.recvfrom(1024))
print(server.recvfrom(1024))

import socket
client = socket.socket(type=socket.SOCK_DGRAM)
server_addr = ('127.0.0.1',8080)
client.sendto(b'hello',server_addr)
client.sendto(b'hello',server_addr)
client.sendto(b'hello',server_addr)

基于UDP实现简易版本的qq

1.服务端

import socket

server = socket.socket(type=socket.SOCK_DGRAM)
server.bind(('127.0.0.1', 8080))
while True:
    msg, addr = server.recvfrom(1024)
    print(addr)
    print(msg.decode('utf-8'))
    info = input('>>>:').encode('utf-8')
    server.sendto(info, addr)

server.close()

2.客户端

import socket

client = socket.socket(type=socket.SOCK_DGRAM)
server_addr = ('127.0.0.1', 8080)

while True:
    info = input('>>>:')
    info = ('来自客户端1的消息:%s'%info).encode('utf-8')  # 改中文备注即可
    client.sendto(info, server_addr)
    msg, addr = client.recvfrom(1024)
    print(msg.decode('utf-8'), addr)

client.close()

总结:
TCP协议就类似于打电话
UDP协议就类似于发短信

SocketServer模块介绍(让tcp也能支持并发)

socketserver是一个socket的服务器模块的使用,在这个模块中,主要也就是实现服务器类的相关功能,在其中,也就是将socket模块和select模块进行了封装,从而创建了一些基类供人使用。

TCP socketserver使用

import socketserver
class MyTcpServer(socketserver.BaseRequestHandler):
    def handle(self):
        while True:
            try:
                data = self.request.recv(1024)  # 对于tcp,self.request相当于conn对象
                if len(data) == 0:break
                print(data)
                self.request.send(data.upper())
            except ConnectionResetError:
                break
if __name__ == '__main__':
    server = socketserver.ThreadingTCPServer(('127.0.0.1',8081),MyTcpServer)
    server.serve_forever()

UDP socketserver使用

import socketserver

class MyUdpServer(socketserver.BaseRequestHandler):
    def handle(self):
        while True:
            data, sock = self.request
            print(data)
            sock.sendto(data.upper(), self.client_address)


if __name__ == '__main__':
    server = socketserver.ThreadingUDPServer(('127.0.0.1', 8080), MyUdpServer)
    server.serve_forever()

首先定义了一个类,也就是处理请求的类,从基类baserequesthandler继承,主要就是重写其中handle方法,告知服务器如何来处理客户端的请求。然后创建了一个线程的TCP服务器类,也就是通过多线程来进行应答客户端,然后使用一直运行的方法也就是serve_forever。

猜你喜欢

转载自blog.csdn.net/linwow/article/details/89848303
今日推荐