传输层:UDP协议
目录
0.socket通信基本流程图
一、传输层协议
从之前介绍的网络层协议来看,通信的两端是两台主机,IP数据报首部就标明了这两台主机的ip地址。但是从传输层来看,是发送方主机中的一个进程与接收方主机中的一个进程在交换数据,因此,严格地讲,通信双方不是主机,而是主机中的进程。
主机中常常有多个应用进程同时在与外部通信(比如你的浏览器和 QQ 在同时运行),下图中,A 主机的 AP1 进程在于B主机的AP3进程通信,同时主机A的AP2 进程也在与B主机的AP4进程通信。
两个主机的传输层之间有一个灰色双向箭头,写着“传输层提供应用进程间的逻辑通信〞。逻辑通信:看起来是数据似乎是沿着双向箭头在传输层水平传输的,但实际上是沿图中的虚线经多个协议层次而传输。
二、端口
端口的作用体现在传输层,端口号有 0~65535 的编号。
刚才的图中,AP1与AP3的通信与AP2与AP4的通信可以使用同一个传输层协议来传输(TCP 或 UDP),根据IP地址或MAC地址都只能是把数据传到正确的主机,但具体需要传到哪一个进程,是通过端口来辨认的。比如同时使用浏览器和 QQ,浏览器占用 80 端口,而 QQ占用 4000 端口,那么发送过来的 QQ 消息便会通过 4000 端口显示在 QQ 客户端,而不会错误地显示在浏览器上。
系统端口号:
应 用 层 协 议 | FTP | TELNET | SMTP | DNS | TFTP | HTTP | SNMP |
系 统 端 口 号 | 21 | 23 | 25 | 53 | 69 | 80 | 161 |
·编号1024~49151为登记端口号,为没有系统端口号的应用程序使用。使用结束后,这类端口号会被开放以供其他程序使用。
三、UDP概述
UDP(User Datagram Protocol)用户数据报协议。它只在IP数据报服务之上增加了很少一点功能,它的主要特点有:
(1)UDP是无连接的,发送数据之前不需要建立连接(而TCP需要),减少了开销和延时;
(2)UDP尽最大努力交付,不保证交付可靠性;
(3)UDP是面向报文的,对于从网络层交付下来的IP数据报,只做简单的封装(8字节UDP报头),首部开销小。
(4)UDP没有拥塞控制,出现网络拥塞时发送方也不会降低发送速率。这种特性对某些实时应用是很重要的,比如IP电话,视频会议等,它们允许拥塞时丢失一些数据,因为如果不抛弃这些数据,极可能造成时延的累积。
(5)UDP支持一对一、一对多、多对一和多对多的交互通信。
从应用层到传输层,再到网络层的各层次封装:
四、UDP报文
UDP数据报可分为两部分:UDP报头和数据部分。其中数据部分是应用层交付下来的数据。UDP报头总共8字节,而这8字节又分为4个字段:
(1)源端口2字节 在对方需要回信时可用,不需要时可以全0;
(2)目的端口2字节 必须,也是最重要的字段;
(3)
(4)校验和2字节 用于检验UDP数据报在传输过程中是否有出错,有错就丢弃。
五、UDP
UDP不需要3次握手4次挥手,不需要提前建立连接,直接发数据进行。
服务器端
连接云服务器
ssh root@43.143.177.190
使用ip='0.0.0.0'的原因
/阿里云端服务器socket绑定阿里云的私网IP或者地址设置为INADDR_ANY
INADDR_ANY转换过来就是0.0.0.0,泛指本机的意思,也就是表示本机的所有IP,因为有些机子不止一块网卡,多网卡的情况下,这个就表示所有网卡ip地址的意思。当服务器的监听地址是INADDR_ANY时,意思不是监听所有的客户端IP。而是服务器端的IP地址可以随意配置,这样使得该服务器端程序可以运行在任意计算机上,可使任意计算机作为服务器,便于程序移植,将INADDR_ANY换成127.0.0.1也可以达到同样的目的。这样,当作为服务器的计算机IP有变动或者网卡数量有增减,服务器端程序都能够正常监听来自客户端的请求。
比如一台电脑有3块网卡,分别连接三个网络,那么这台电脑就有3个ip地址了,如果某个应用程序需要监听某个端口,那他要监听哪个网卡地址的端口呢?如果绑定某个具体的ip地址,你只能监听你所设置的ip地址所在的网卡的端口,其它两块网卡无法监听端口,如果我需要三个网卡都监听,那就需要绑定3个ip,也就等于需要管理3个套接字进行数据交换,这样岂不是很繁琐?所以出现INADDR_ ANY,你只需绑定INADDR_ANY,管理一个套接字就行,不管数据是从哪个网卡过来的,只要是绑定的端口号过来的数据,都可以接收到。
代码实现
#-*- coding: UTF-8 -*-
import socket
ip = '0.0.0.0'#不可以直接写公网ip
port = 9000
#套接字家族
sk = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
sk.bind((ip,port))
while True:
msg,addr = sk.recvfrom(1024)
print('recv:',msg, addr)
sk.sendro(masg.upper(),addr)
报错
SyntaxError: Non-ASCII character '\xe4' in file udpserver.py on line 3, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details
报错原因及解决方法
在编写Python时,当使用中文输出或注释时,运行脚本会提示以上错误信息,因为python的默认编码文件是用的ASCII码,你将文件存成了UTF-8,解决办法很简单,在文件开头加入:# -*- coding: UTF-8 -*- 或者 #coding=utf-8
客户端
代码实现
import socket
ip = '47.100.89.39'
port = 9000
sk = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
while True:
msg = input('>>>>:').strip()
if not msg: continue
sk.sendto(msg.encode('utf-8'),(ip,port))
back, addr = sk.recvfrom(1024)
print(back.decode('utf-8'),addr)
运行结果
六、tcpdump抓取UDP报文
现在我们动手实践,尝试抓取一个UDP数据报,并解读其内容。
我们需要一个小程序,用于向指定IP地址的指定端口发送一个指定内容的UDP数据报,这个程序已经编写好了,依次输入以下命令,使用github把它下载下来,并编译:
cd Desktop
cd tcp ip 5
gcc -o test test.c
基于TCP的聊天小程序,分为server(服务端)和client(客户端):
编译完成后先不要运行,先打开tcpdump,使用命令安装并运行tcpdump:
sudo apt-get update
sudo apt-get install tcpdump
sudo tcpdump -vvv -X udp port 9000 and host 47.100.89.39
七、TCP vs UDP
TCP:是可靠的,建立连接,三次握手,四次挥手,stream字节流,listen,accept,connect,粘包现象;
UDP:不可靠的,datagram,基于报文,无连接,最大努力投递,消息有边界。
八、总结
1.掌握常见网络词汇的意思。
3.基于Python的socket模块实现网络编程。