UDP通信

1.网络目的和IP地址的意义

##1.1 网络

网络能够把多方链接在一起,然后可以进行数据传递

网络编程就是,让在不同的电脑上的软件能够进行数据传递,即进程之间的通信

##1.2 ip地址

ip地址:用来在网络中标记一台电脑,比如192.168.1.1;在本地局域网上是唯一的。



2.IP地址分类(了解)


##2.1A类IP地址

一个A类IP地址由1字节的网络地址和3字节主机地址组成,网络地址的最高位必须是“0”,

地址范围1.0.0.1-126.255.255.254

二进制表示为:00000001 00000000 00000000 00000001 - 01111110 11111111 11111111 11111110

可用的A类网络有126个,每个网络能容纳1677214个主机

##2.2B类IP地址

一个B类IP地址由2个字节的网络地址和2个字节的主机地址组成,网络地址的最高位必须是“10”,

##2.3 C类IP地址

一个C类IP地址由3字节的网络地址和1字节的主机地址组成,网络地址的最高位必须是“110”

## 2.4 D类地址用于多点广播

D类IP地址第一个字节以“1110”开始,它是一个专门保留的地址。

它并不指向特定的网络,目前这一类地址被用在多点广播(Multicast)中

多点广播地址用来一次寻址一组计算机 s 地址范围224.0.0.1-239.255.255.254

## 2.3 E类IP地址

以“1111”开始,为将来使用保留

E类地址保留,仅作实验和开发用

## 2.6 私有IP

在这么多网络IP中,国际规定有一部分IP地址是用于我们的局域网使用,也就

是属于私网IP,不在公网中使用的,它们的范围是:

10.0.0.0~10.255.255.255

172.16.0.0~172.31.255.255

192.168.0.0~192.168.255.255

## 2.7 IP地址

IP地址127.0.0.1~127.255.255.255用于回路测试,

如:127.0.0.1可以代表本机IP地址,用http://127.0.0.1就可以测试本机中配置的Web服务器。

## 2.8  ifconfig  ping作用

###2.8.1 ifconfig,它会显示所有网卡的信息

UDP通信_第1张图片

###2.8.2 通常用ping来检测网络是否正常,测试远程主机的连通性

UDP通信_第2张图片



3.端口的作用

##3.1 什么是端口

UDP通信_第3张图片

UDP通信_第4张图片

##3.2 端口号

端口是通过端口号来标记的,端口号只有整数,范围是从0到65535

注意:端口数不一样的*nix系统不一样,还可以手动修改

##3.3 在linux系统中,端口可以有65536(2的16次方)个之多!

##3.4 端口分配

端口号不是随意使用的,而是按照一定的规定进行分配。

###3.4.1 知名端口

知名端口是众所周知的端口号,范围从0到1023

可以理解为,一些常用的功能使用的号码是估计的,好比 电话号码110、10086、10010一样

80端口分配给HTTP服务
21端口分配给FTP服务

###3.4.2

动态端口的范围是从1024到65535

之所以称为动态端口,是因为它一般不固定分配某种服务,而是动态分配。

动态分配是指当一个系统程序或应用程序程序需要网络通信时,它向主机申请一个端口,主机从可用的端口号中分配一个供它使用。

当这个程序关闭时,同时也就释放了所占用的端口号


4.socket套接字概念

##4.1 套接字概念

socket(简称套接字) 是进程间通信的一种方式,它与其他进程间通信的一个主要不同是:

它能实现不同主机间的进程间通信,我们网络上各种各样的服务大多都是基于 Socket 来完成通信的

UDP通信_第5张图片

##4.2创建套接字

在 Python 中 使用socket 模块的函数 socket 就可以完成:

import socket
socket.socket(AddressFamily, Type)

说明:

函数 socket.socket 创建一个 socket,该函数带有两个参数:

  • Address Family:可以选择 AF_INET(用于 Internet 进程间通信) 或者 AF_UNIX(用于同一台机器进程间通信),实际工作中常用AF_INET
  • Type:套接字类型,可以是 SOCK_STREAM(流式套接字,主要用于 TCP 协议)或者 SOCK_DGRAM(数据报套接字,主要用于 UDP 协议)

创建一个udp socket(udp套接字)

import socket

# 创建udp的套接字
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# ...这里是使用套接字的功能(省略)...

# 不用的时候,关闭套接字
s.close()

说明:

套接字使用流程和文件使用流程相似

    1.创建套接字

    2.使用套接字接/发数据

    3.关闭套接字


5.udp初步发送数据

##5.1UDP发送数据

UDP通信_第6张图片

代码如下:

#coding=utf-8

from socket import *

# 1. 创建udp套接字
udp_socket = socket(AF_INET, SOCK_DGRAM)

# 2. 准备接收方的地址
# '192.168.1.103'表示目的ip地址
# 8080表示目的端口
dest_addr = ('192.168.1.103', 8080)  # 注意 是元组,ip是字符串,端口是数字

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

# 4. 发送数据到指定的电脑上的指定程序中
udp_socket.sendto(send_data.encode('utf-8'), dest_addr)

# 5. 关闭套接字
udp_socket.close()

运行现象:

在Ubuntu中运行脚本:


##5.2使用网络调试助手

UDP通信_第7张图片


6.str和bytes类型的相互转化

str->bytes:encode编码
bytes->str:decode解码

字符串通过编码成为字节码,字节码通过解码成为字符串。

>>> text = '我是文本'
>>> text
'我是文本'
>>> print(text)
我是文本
>>> bytesText = text.encode()
>>> bytesText
b'\xe6\x88\x91\xe6\x98\xaf\xe6\x96\x87\xe6\x9c\xac'
>>> print(bytesText)
b'\xe6\x88\x91\xe6\x98\xaf\xe6\x96\x87\xe6\x9c\xac'
>>> type(text)

>>> type(bytesText)

>>> textDecode = bytesText.decode()
>>> textDecode
'我是文本'
>>> print(textDecode)
我是文本

其中decode()与encode()方法可以接受参数,编码默认是utf-8,其声明分别为:

bytes.decode(encoding="utf-8", errors="strict")
str.encode(encoding="utf-8", errors="strict")

其中的encoding是指在解码编码过程中使用的编码(此处指“编码方案”是名词),errors是指错误的处理方案。

详细的可以参照官方文档:

  • str.encode()
  • bytes.decode()


7.bind()函数的作用-实现使用固定的端口

##7.1一般情况下,在一台电脑上运行的网络程序有很多,为了不与其他的网络程序占用同一个端口号,往往在编程中,udp的端口号一般不绑定

但是如果需要做成一个服务器端的程序的话,是需要绑定的,想想看这又是为什么呢?

如果报警电话每天都在变,想必世界就会乱了,所以一般服务性的程序,往往需要一个固定的端口号,这就是所谓的端口绑定

UDP通信_第8张图片

一个udp网络程序,也可以绑定信息(ip地址,端口号),如果绑定成功,那么操作系统用这个端口号来进行区别收到的网络数据是否是此进程的

8.echo服务器

import socket


# 创建套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# 绑定固定端口
udp_socket.bind(('', 9999))

# 回射接收到的消息
while True:
    # 接收消息
    recv_data, remote_address = udp_socket.recvfrom(4096)
    print("接收到了%s发来的消息%s" % (str(remote_address), recv_data.decode()))

    # 回射
    udp_socket.sendto(recv_data, remote_address)

9.案例-聊天工具代码实现-总结

import socket


def send_message(udp_socket):
    # 输入的内容
    data = input("请输入您要发送的信息内容:")
    # ip
    ip = input("请输入对方的ip地址:")
    # 端口
    port = int(input("请输入端口:"))

    # 发送数据
    udp_socket.sendto(data.encode(), (ip, port))


def receive_message(udp_socket):
    recv_data, romote_address = udp_socket.recvfrom(4096)
    print("收到了来自%s的回信%s" % (str(romote_address), recv_data.decode()))


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

    # 绑定固定端口
    udp_socket.bind(("", 9898))

    while True:
        # 输入指示
        command = input("请输入您要执行的功能 1.发送消息 2.接收消息 3.退出")
        # 发送数据
        if command == '1':
            send_message(udp_socket)
        # 接收数据
        elif command == '2':
            receive_message(udp_socket)
        # 退出
        elif command == '3':
            break
        else:
            print("输入有误,请重新输入")


if __name__ == '__main__':
    main()

你可能感兴趣的:(UDP通信)