网络编程
udp网络程序—发送、接收数据
创建一个基于udp的网络程序流程很简单,具体步骤如下:
1、创建客户端套接字
2、发送/接收数据
3、关闭套接字
发送数据代码如下
import socket
def main():
# 创建一个udp套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
while True:
# 从键盘获取数据
send_data = input("请输入要发送的数据:")
# 如果输入的是exit,那么久退出程序
if send_data == "exit":
break
# 可以使用套接字收发数据
# udp_socket.sendto("hello", 对方的ip及port)
# udp_socket.sendto("hello", ("192.168.xx.xx", 12707))
udp_socket.sendto(send_data.encode("utf-8"), ("192.168.33.128", 12707))
# 关闭套接字
udp_socket.close()
print("-----run-----")
if __name__ == "__main__":
main()
接收数据代码如下
import socket
def main():
# 1.创建套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 2.绑定一个本地信息 【元组】
localaddr = ('', 12707) # ip地址和端口号,ip地址一般不用写,表示本机的任何一个ip
udp_socket.bind(localaddr) # 必须绑定自己电脑的IP 和 port ,其他人的不行
while True:
# 3.接收数据
recv_date = udp_socket.recvfrom(1024) # 1024表示本次接收的最大字节数
# recv_data 这个变量中存储的是一个元组 (接收到的数据,(发送方的IP,发送方的port))
recv_msg = recv_date[0] # 存储接收大数据
send_addr = recv_date[1] # 存储发送方的地址信息
# 4.打印接收到的数据
# print(recv_date)
print("%s:%s" % (str(send_addr), recv_msg.decode("gbk"))) # 接收到的数据是win系统发送过来的,所以使用GBK编码,而不是utf-8
# 5.关闭套接字
udp_socket.close()
if __name__ == "__main__":
main()
发送数据的流程
1、创建套接字
2、发送数据
3、关闭
接收数据的流程
1、创建套接字
2、绑定本地自己的信息(IP和Port)
3、接收数据
4、关闭
端口绑定的问题
- 同一时刻,不允许有相同的端口号
单工、半双工与全双工
- 单工:百分之百只能指向一个方向走,比如收音机…
- 半双工:对讲机,可以收也可以发。但是收的时候发不了,发的时候收不了。
- 全双工:既可以收也可以发,如打电话。【socket套接字时全双工】
应用:udp聊天器
需求
在一个电脑中编写一个程序,有两个功能
1、获取键盘的数据,并将其发送给对方
2、接收数据并显示
并且功能数据进行选择以上的两个功能调用
代码如下
import socket
def send_msg(udp_socket):
"""发送消息"""
# 获取要发送的内容
send_data = input("请输入 要发送的消息:")
dest_ip = input("请输入对方的IP:")
dest_port = int(input("请输入对方的PORT:"))
udp_socket.sendto(send_data.encode("utf-8"), (dest_ip, dest_port))
def recv_msg(udp_socket):
"""接收数据"""
recv_data = udp_socket.recvfrom(1024)
print("%s:%s" % (str(recv_data[1]), recv_data[0].decode("utf-8")))
def main():
"""程序入口"""
# 创建套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 绑定信息
udp_socket.bind(("", 12707))
# 循环来处理
while True:
# 发送
send_msg(udp_socket)
# 接收并显示
recv_msg(udp_socket)
if __name__ == "__main__":
main()
- 但是上述的流程太固定了,必须先发送,才能再接收。如果不发送消息,就会一直卡在这里。能够针对流程再一次进行优化呢?
参考代码如下
import socket
def send_msg(udp_socket):
"""发送消息"""
# 获取要发送的内容
send_data = input("请输入 要发送的消息:")
dest_ip = input("请输入对方的IP:")
dest_port = int(input("请输入对方的PORT:"))
udp_socket.sendto(send_data.encode("utf-8"), (dest_ip, dest_port))
def recv_msg(udp_socket):
"""接收数据"""
recv_data = udp_socket.recvfrom(1024)
print("%s:%s" % (str(recv_data[1]), recv_data[0].decode("utf-8")))
def main():
"""程序入口"""
# 创建套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 绑定信息
udp_socket.bind(("", 12707))
# 循环来处理
while True:
print("-----xx聊天器-----")
print("1:发送消息")
print("2:接收消息")
print("0:退出系统")
op = input("请输入要选择的功能:")
if op == "1":
# 发送
send_msg(udp_socket)
elif op == "2":
# 接收并显示
recv_msg(udp_socket)
elif op == "0":
break
else:
print("输入有误,请重新输入...")
if __name__ == "__main__":
main()