python全栈(一)网络通信与服务器之网络-udp

前言

本系列博文《网络通信与服务器》主要内容:udp、tcp、tcp下载文件案例、多任务、http协议、网络通信等 。本篇博文主要讲解网络中的udp。

概念介绍

网络中重要概念:

网络通信方式有两种方式:udp, tcp
IP目的:用来标记网络上的一台电脑或其他设备。
IP传输数据(局域网)的流程如下:
在这里插入图片描述
端口分类
知名端口:
范围是从0到1023。
80端口分配给HTTP服务
21端口分配给FTP服务
动态端口:
范围是从1024-65535。
手机连的3G4G得ip是全世界唯一得,是公有ip,在家通过路由器间接上的网,分得ip, 连的是私有IP.
ip在网络上来标记一台电脑,port标记一个程序
一个ip在一个网络里不可以相同,一个port在一个电脑里,不可以相同。
端口是为了识别不同的应用程序而分配给不同的应用的。
同一个端口,同一个时刻,不允许使用两次,也就是不会给两个程序分配同一个端口号;一个程序对应分配一个端口号。

Socket的简单使用

1.TCP/IP协议
TCP/IP协议是Transmission Control Protocol/Internet Protocol的简写,即传输控制协议/因特网互联协议,又名网络通讯协议,是Internet最基本的协议、Internet国际互联网络的基础,由网络层的IP协议和传输层的TCP协议组成。
TCP/IP定义了电子设备如何连入因特网,以及数据如何在它们之间传输的标准。协议采用了4层的层级结构,每一层都呼叫它的下一层所提供的协议来完成自己的需求。
2.Socket
socket又称套接字,应用程序通常通过套接字向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯。
白话说,socket就是两个节点为了互相通信,而在各自家里装的一部电话。
TCP/IP各层之间传输数据的过程,如图:
在这里插入图片描述
增加Socket(在应用层和传输层之间)之后传输数据的过程, 如图:
在这里插入图片描述
family是协议族,默认AF_INET是IPv4,AF_INET6是IPv6;
type是套接字类型,包括TCP和UDP两种,默认SOCK_STREAM是流式套接字,属于TCP,SOCK_DGRAM是数据报套接字,属于UDP。
socket的简单使用:
socket的使用过程:

  • 创建套接字
  • 使用套接字收/发数据
  • 关闭套接字

代码示例

import socket

#创建套接字
s = socket.socket(family=socket.AF_INET,type=socket.SOCK_DGRAM)
#使用套接字收发数据
pass
#关闭套接字
s.close()

udp通信模型

udp通信模型中,在通信开始之前,不需要建立相关的链接,只需要发送数据即可,类似于生活中“写信”。(udp几乎不用)如下图所示:
在这里插入图片描述

代码示例讲解

01-socket的基本使用

import socket

def main():
    # 创建一个udp套接字
    udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    # 可以使用套接字收发数据
    # udp_socket.sendto("hahahah", 对方的ip以及port)
    udp_socket.sendto(b"hahahah------1----", ("192.168.33.53", 8080))

    # 关闭套接字
    udp_socket.close()
	
if __name__ == "__main__":
    main()

02-发送任意数据给windows中调试助手

import socket

def main():
    # 创建一个udp套接字
    udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    # 从键盘获取数据
    send_data = input("请输入要发送的数据:")

    # 可以使用套接字收发数据
    # udp_socket.sendto("hahahah", 对方的ip以及port)
    # udp_socket.sendto(b"hahahah------1----", ("192.168.33.53", 8080))
    udp_socket.sendto(send_data.encode("utf-8"), ("192.168.33.53", 8080))

    # 关闭套接字
    udp_socket.close()
    
if __name__ == "__main__":
    main()

03-循环发送数据

import socket

def main():
    # 创建一个udp套接字
    udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    
    while True:
        # 从键盘获取数据
        send_data = input("请输入要发送的数据:")
        
        # 可以使用套接字收发数据
        # udp_socket.sendto("hahahah", 对方的ip以及port)
        # udp_socket.sendto(b"hahahah------1----", ("192.168.33.53", 8080))
        udp_socket.sendto(send_data.encode("utf-8"), ("192.168.33.53", 8080))
        
    # 关闭套接字
    udp_socket.close()
	
if __name__ == "__main__":
    main()

04-带有退出功能的循环发送

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("hahahah", 对方的ip以及port)
        # udp_socket.sendto(b"hahahah------1----", ("192.168.33.53", 8080))
        udp_socket.sendto(send_data.encode("utf-8"), ("192.168.33.53", 8080))

    # 关闭套接字
    udp_socket.close()
	
if __name__ == "__main__":
    main()

05-绑定端口用来接收数据

import socket

def main():
    # 1. 创建套接字
    udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    # 2. 绑定一个本地信息,如果一个网络程序不绑定,则系统会随机分配
    localaddr = ("", 7788)  # ip地址和端口号,ip一般不用写,表示本机的任何一个ip
    udp_socket.bind(localaddr)
    # 3. 接收数据
    recv_data = udp_socket.recvfrom(1024)
    # 4. 打印接收到的数据
    print(recv_data)
    # 5. 关闭套接字
    udp_socket.close()

if __name__ == "__main__":
    main()

06-解析出接收到的数据

import socket

def main():
    # 1. 创建套接字
    udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    # 2. 绑定一个本地信息
    localaddr = ("", 7788)
    udp_socket.bind(localaddr)  # 必须绑定自己电脑的ip以及port,其他的不行
    # 3. 接收数据
    recv_data = udp_socket.recvfrom(1024)
    # recv_data这个变量中存储的是一个元组(接收到的数据,(发送方的ip, port))
    recv_msg = recv_data[0]  # 存储接收的数据
    send_addr = recv_data[1]  # 存储发送方的地址信息
    # 4. 打印接收到的数据
    # print(recv_data)
    # print("%s:%s" % (str(send_addr), recv_msg.decode("utf-8")))
    print("%s:%s" % (str(send_addr), recv_msg.decode("gbk")))
    # 5. 关闭套接字
    udp_socket.close()

if __name__ == "__main__":
    main()

07-循环接收并显示数据

import socket

def main():
    # 1. 创建套接字
    udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    # 2. 绑定一个本地信息
    localaddr = ("", 7788)
    udp_socket.bind(localaddr)  # 必须绑定自己电脑的ip以及port,其他的不行

    # 3. 接收数据
    while True:
        recv_data = udp_socket.recvfrom(1024)
        # recv_data这个变量中存储的是一个元组(接收到的数据,(发送方的ip, port))
        recv_msg = recv_data[0]  # 存储接收的数据
        send_addr = recv_data[1]  # 存储发送方的地址信息
        # 4. 打印接收到的数据
        # print(recv_data)
        # print("%s:%s" % (str(send_addr), recv_msg.decode("utf-8")))
        print("%s:%s" % (str(send_addr), recv_msg.decode("gbk")))
    # 5. 关闭套接字
    udp_socket.close()

if __name__ == "__main__":
    main()

08-先绑定端口然后在循环发送
udp_socket.bind((ip, port))

import socket

def main():
    # 创建一个udp套接字
    udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    # 绑定本地信息
    udp_socket.bind(("", 7890))

    while True:

        # 从键盘获取数据
        send_data = input("请输入要发送的数据:")

        # 可以使用套接字收发数据
        # udp_socket.sendto("hahahah", 对方的ip以及port)
        # udp_socket.sendto(b"hahahah------1----", ("192.168.33.53", 8080))
        udp_socket.sendto(send_data.encode("utf-8"), ("192.168.33.53", 8080))
        
    # 关闭套接字
    udp_socket.close()
	
if __name__ == "__main__":
    main()

09-使用同一个套接字进行收发数据

模板:

import socket

def main():
	# 创建一个udp套接字
	udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
	
	# 绑定本地信息
	# 端口绑定问题:如果程序运行时,没有绑定端口,那么操作系统会自动分配一个端口给程序;
    udp_socket.bind((ip, port))  
    
	# 可以使用套接字收发数据
	udp_socket.sendto(send_data.encode("utf-8"), (dest_ip, dest_port)) # window "gbk"
	
	# 接收回送过来的数据
	recv_data = udp_socket.recvfrom(1024)  # 如果recvfrom()的参数指定过小,超过发送的数据的大小,则会报错。记住一定要写数值
	
	# 关闭套接字
	udp_socket.close()

接收到的数据为元组形式,其中,
第一个值为接收到的数据;
第二个值为(发送方的IP,端口)。

import socket

def main():
    # 创建一个udp套接字
    udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    # 获取对方的ip/port
    dest_ip = input("请输入对方的ip:")
    dest_port = int(input("请输入对方的port:"))

    # 从键盘获取数据
    send_data = input("请输入要发送的数据:")

    # 可以使用套接字收发数据
    # udp_socket.sendto("hahahah", 对方的ip以及port)
    # udp_socket.sendto(b"hahahah------1----", ("192.168.33.53", 8080))
    # udp_socket.sendto(send_data.encode("utf-8"), ("192.168.33.53", 8080))
    udp_socket.sendto(send_data.encode("utf-8"), (dest_ip, dest_port))

    # 接收回送过来的数据
    recv_data = udp_socket.recvfrom(1024)
    # 套接字是一个可以同时 收发数据
    print(recv_data)

    # 关闭套接字
    udp_socket.close()
	
if __name__ == "__main__":
    main()

应用–生成UDP聊天器

10-案例:udp聊天

import socket

def send_msg(udp_socket):
    """发送消息"""
    # 获取要发送的内容
    dest_ip = input("请输入对方的ip:")
    dest_port = int(input("请输入对方的port:"))
    send_data = input("请输入要发送的消息:")
    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(("", 7788))

    # 循环循环来进行处理事情
    while True:
        # 发送
        send_msg(udp_socket)

        # 接收并显示
        recv_msg(udp_socket)

if __name__ == "__main__":
    main()

11-案例:udp聊天-升级-可以控制操作
终结版代码

import socket

def send_msg(udp_socket):
    """发送消息"""
    # 获取要发送的内容
    dest_ip = input("请输入对方的ip:")
    dest_port = int(input("请输入对方的port:"))
    send_data = input("请输入要发送的消息:")
    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(("", 7788))

    # 循环循环来进行处理事情
    while True:
        print("-----xxx聊天器-----")
        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()

总结

步骤:

  1. 创建套接字 套接字是可以同时收发数据的
  2. 发送数据
  3. 接收数据

接收到的数据为元组形式,其中,
第一个值为接收到的数据;
第二个值为(发送方的IP,端口)。

端口绑定问题:
如果程序运行时,没有绑定端口,那么操作系统会自动分配一个端口给程序;而且同一端口,不能用两次。

UDP收发数据的过程

  1. 创建套接字
  2. 绑定本地信息(IP和端口)
  3. 接收数据(接受数据的时候,注意解码-将二进制转换过来)
  4. 显示或处理数据
  5. 发送数据(发送数据时,注意编码(变成二进制))
  6. 关闭套接字
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值