网络编程之基于UDP协议套接字

1.UDP协议介绍(数据报协议)

  UDP协议不同于TCP,通信时,它不需要事先建立双向链接,并且不区分客户端先启动还是服务端前起,工作原理:基于udp协议传输的信息,协议会将数据自动加上自定义的报头,这样每一个数据都是一个数据报,而流失协议由于自身优化算法,产生粘包现象,udp不会产生粘包现象,并且发出的消息可以为空,因为就算你发的是空消息,协议也会给你的空消息加上一段自定义报头,所以它还是一个数据报,而tcp协议在这里则不能发空消息,一旦发空消息,接收方会一直处于收的状态,发送方发完空后会一直处于收的状态,所以对于tcp协议需要加上一些异常处理代码,防止异常的发生,

  为什么说udp协议是不可靠而tcp是可靠的呢?这里面试可能会被问到,答案没你想得那么简单(因为tcp是基于双向链接而udp没有基于链接,数据发出去就行了~~~这么回答估计你这次面试也就GG了,背后的真正的原理:):首先必须搞清楚一个大的原理,应用程序收发消息都是跟谁打交道的???——没错是应用程序自身所在的操作系统,知道这一点之后,再来说,为什么tcp协议可靠,原因在于服务端向客户端发出数据(这里的数据也是先流到服务端的操作系统内存由服务端操作系统向客户端发)后,客户端必须向服务端发出确认消息,而服务端发出的数据,操作系统不会立即将内存中的数据立马清除,而是会等到确认消息后,才会清理数据内存,这个时候的数据才是无用的,如果没有收到确认信息,服务端隔断时间会再向客户端发送内存里存好的数据,这才是tcp协议通信的可靠的本质,

  反观udp则比较随性了,发送端将数据写好点击发送后,数据会被加上自定义报头然后由操作系统发出,发出后立马清除数据内存,要想用udp有效的传输数据,最大数据传输范围应该控制在512bytes,数据量超过这个限制,就无法再保证数据传输的稳定性了。

2.tcp协议完整代码逻辑

import socket

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

while True:
    msg=input('>>>: ').strip()
    if not msg:continue
    client.send(msg.encode('utf-8'))
    data=client.recv(1024)
    print(data.decode('utf-8'))

client.close()
客户端
import socket

server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind(('127.0.0.1',8080))
server.listen(5)

while True:
    conn,client_addr=server.accept()
    print(client_addr)

    while True:
        try:
            data=conn.recv(1024)
            if not data:break # 针对linux系统
            conn.send(data.upper())
        except ConnectionResetError:
            break
    conn.close()

server.close()
服务端

3.udp协议代码

客户端:

import socket

client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) # 数据报协议

while True:
    msg=input('>>>: ').strip()
    client.sendto(msg.encode('utf-8'),('127.0.0.1',8080))
    res,server_addr=client.recvfrom(1024)
    print(res.decode('utf-8'))

服务端:

import socket

server=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) # 数据报协议
server.bind(('127.0.0.1',8080))

while True:
    client_data,client_addr=server.recvfrom(1024)
    msg=input('回复%s:%s>>>:' %(client_addr[0],client_addr[1]))
    server.sendto(msg.encode('utf-8'),client_addr)

4.基于udp写实现网络沟通交流(建议版本qq)

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

while True:
    data,client_addr=server.recvfrom(1024)
    print('get a message form %s:%s>>:%s'%(client_addr[0],client_addr[1],data.decode('utf-8')))
    msg=input('please recall>>:').strip()
    server.sendto(msg.encode('utf-8'),client_addr)
import socket
client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

while True:
    msg=input('what are you want to talk>>:').strip()
    if not msg:continue
    client.sendto(msg.encode('utf-8'),('127.0.0.1',8808))
    msg,addr=client.recvfrom(1024)
    print('get a message from %s:%s>>:%s'%(addr[0],addr[1],msg.decode('utf-8')))

5.基于udp协议编写时间服务器(访问就给你放回当前时间)

服务端

import socket,time
server=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
server.bind(('127.0.0.1',8808))

while True:
    data,client_addr=server.recvfrom(1024)
    if not data:
        time_list=time.strftime('%Y-%m-%d %X')
    else:
        time_list=time.strftime(data.decode('utf-8'))
    server.sendto(time_list.encode('utf-8'),client_addr)

访问端

import socket
client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

while True:
    msg=input('please input the format of time which are you want get>>:').strip()
    client.sendto(msg.encode('utf-8'),('127.0.0.1',8808))
    data,addr=client.recvfrom(1024)
    print('time>>:%s'%data.decode('utf-8'))

猜你喜欢

转载自www.cnblogs.com/Dominic-Ji/p/8920377.html