Python之网络编程(TCP套接字与UDP套接字)
原创
©著作权归作者所有:来自51CTO博客作者mb62e7593c01ba5的原创作品,请联系作者获取转载授权,否则将追究法律责任
文章目录
本篇文章继续研究Socket编程,上篇文章:Python之网络编程(socket基础)已经详细介绍过Socket编程的基础知识,其中也包括了tcp协议的工作流程。本篇就通过小案例继续分析tcp与udp的用法及功能
基于tcp的套接字
实现目标
(1)循环多链接并且循环收发消息
(2)可服务多个客户端,并且不断与客户端收发消息(但不可同时服务多个客户端,下文中的udp协议可以做到同时服务多个客户端)
tcp服务端源码
from socket import *
ip_port = ('192.168.43.247',8080) #记录ip地址
back_log = 5
buffer_size = 1024
tcp_server = socket(AF_INET,SOCK_STREAM)
#规定服务端可以重新使用ip地址
tcp_server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
tcp_server.bind(ip_port) #绑定IP地址
tcp_server.listen(back_log) #监听信号
#实现循环接收多链接,同时服务多个客户端
while True:
#该语句用来表明状态
print('================服务端开始运行了================')
conn,addr = tcp_server.accept() #接收对方的链接和地址
print('双向链接是:',conn)
print('客户端地址是:',addr)
#实现循环收发消息
while True:
try: #用异常处理来解决当服务端断开以后,跳出上一个链接的循环
data = conn.recv(buffer_size) #buffer_size默认参数,接收消息
print('客户端发来的消息是:',data.decode('utf-8')) #接收到的消息要解码
conn.send(data.upper()) #把收到的消息变成大写
except Exception :
break
conn.close() #循环一个链接后就关闭这个链接
tcp_server.close() #关闭socket对象
tcp客户端源码
from socket import *
ip_port = ('192.168.43.247',8080) #记录ip地址
back_log = 5
buffer_size = 1024
tcp_client = socket(AF_INET,SOCK_STREAM)
tcp_client.connect(ip_port)
#实现循环发收消息
while True:
msg = input('请输入>>>').strip() #去除输入中的空格
if not msg:continue #如果为空字符(没有输入),就重新输入
tcp_client.send(msg.encode('utf-8')) #发消息
print('客户端已发送出消息!') #接收到的消息要解码
#接收消息
data = tcp_client.recv(buffer_size) #buffer_size=1024默认参数,表示字节格式
print('服务端发回的消息是:',data.decode('utf-8'))
tcp_client.close() #关闭socket对象
tcp效果实现
tcp服务端:
tcp客户端:
基于udp的套接字
udp作用介绍
(1)udp是一种没有链接的套接字,腾讯QQ就是根据udp协议通信的。
(2)为何udp套接字的服务端不需要获取对方的链接?
====>因为客户端每次发消息时都会指定发给哪个服务端
(3)recv与recvfrom的区别
recv在自己这端的缓冲区为空时,会阻断
recvfrom在自己这端的缓冲区为空时,就收一个空
(4)udp服务端的并行不冲突
udp服务端可以直接与多个客户端建立通信,不会冲突;
而tcp服务端不能直接实现并发的效果,需要特殊处理,否则只能同时服务一个客户端
原因: udp不需要建立链接,客户端每次收发都是指定好了发给哪个服务端的地址
udp服务端源码
from socket import *
ip_port = ('192.168.43.247',8080)
buffer_size = 1024 #表示字节形式
udp_server = socket(AF_INET,SOCK_DGRAM) #SOCK_DGRAM是数据报套接字,即udp套接字
udp_server.bind(ip_port)
#因为不需要链接,所以可以直接进入循环
while True:
#接收消息
data,addr = udp_server.recvfrom(buffer_size) #把内容赋给data,地址和端口赋给addr
print('从客户端收到的消息是:',data)
#data = udp_server.recvfrom(buffer_size)
#这样的data是一个元组,里面包括了,内容,服务端的ip地址,服务端的端口
#服务端发回客户端消息
udp_server.sendto(data.upper(),addr) #addr是对方的地址和端口
udp客户端源码
from socket import *
ip_port = ('192.168.43.247',8080)
buffer_size = 1024 #表示字节形式
udp_client = socket(AF_INET,SOCK_DGRAM) #SOCK_DGRAM是数据报套接字,即udp套接字
#开始循环收发消息
while True:
msg = input('请输入>>>') #指定输入消息
udp_client.sendto(msg.encode('utf-8'),ip_port)
#udp套接字需要用sendto发消息,第一个参数是消息内容,第二个参数是服务端的ip地址
#这样就可以让客户端每次都发给指定的服务端,而服务端不需要获取客户端的链接
#客户端接收消息
data,addr = udp_client.recvfrom(buffer_size) #以字节形式接收消息
#因为收到的是一个元组,所以把内容赋给data,地址赋给addr
print(data.decode('utf-8')) #解码并输出消息
udp效果实现
客户端:
客户端并发:
用udp实现一个时间接收器
每发送一次请求就返回一个时间
原理就是上文的udp服务端与客户端代码,文章里传上了py文件,需要的请自行下载