UDP
ip地址的分类
ip地址由两部分构成:网络号和主机号

A类IP地址
一个A类IP地址由1个字节的网络地址和3字节的主机地址组成,网络地址的最高位必须是“0”,地址范围1.0.0.1-126.255.255.254
可用的A类网络有126个,每个网络能容纳1677214个主机
B类IP地址
一个B类IP地址由2个字节的网络地址和2个字节的主机地址组成,网络地址的最高位必须是“10”
可用的B类网络有16384个,每个网络能容纳65534个
C类IP地址
一个C类IP地址由3个字节的网络地址和1个字节的主机地址组成,网络地址的最高位必须是“110”
C类网络可达2097152个,每个网络能容纳254个主机
D类地址用于多点广播
D类IP地址第一个字节以“1110”开始,他是一个专门保留的地址。
它并不指向特定的网络,目前这一类地址被用在多点广播中
多点广播地址用来一次寻址一组计算机s地址范围224.0.0.1-239.255.255.254
E类IP地址
以“1111”开始,为将来保留,仅作实验和开发用
私有IP
10.0.0.1-10.255.255.255
172.16.0.0-172.31.255.255
192.168.0.0.-192.168.255.255
注意
地址127.0.0.1-127.255.255.255用于回路测试,127.0.0.1代表本机,每个主机都有一个IP地址为127.0.0.1
ifconfig/ipconfig
查看所有网卡信息
ping
检测网络是否畅通
能ping通说明网络一定是通畅的,ping超时则可能不通畅或者通畅情况下其他原因导致。
端口
端口是通过端口号来标记的,端口号只有整数,范围0-65535
知名端口
众所周知的端口号,范围是0-1023
80--HTTP
21--FTP
22--SSH
443--HTTPS
一般情况下,如果一个程序需要使用知名端口的需要超级管理员权限
动态端口
动态端口的范围是1024-65535
程序需要网络通信是,向主机申请了一个端口,系统从可用的端口号中分配一个,当这个程序关闭时,同时也就释放了所占用的端口号。
查看端口
用netstat -an 查看端口状态
lsof -i [tcp/udp]:2425
SOCKET
* 所谓“进程”指的是:运行的程序以及运行时用到的资源,这个整体称为“进程”
* 所谓“进程间通信”指的是:运行的程序之间的实现数据共享和传递
创建SOCKET
在python纵,使用socket模块的函数socket就可以完成
import socket
socket.socet(addressFamily,Type)
- addressFamily:可以选择AF_INET(用于Internet进程间通信,表示IPV4协议)或者AF_INET6(表示IPv6协议)
- Type:套接字类型,可以是SOCK_DGRAM(数据报套接字,主要用于UDP协议)或者SOCK_STREAM(流式套接字,主要用于TCP协议)
- UDP和TCP是两种比较常见的套接字类型,其中UDP使用比较简单。
关闭套接字
在不是用的时候关闭套接字,释放资源
sock.close()
发送数据:
发送成功数据数目=sock.sendto(数据,目标主机套接字地址)
接受数据:
data,发送方套接字地址 = sock.recvfrom(最大接收数)
编码转换
str-->bytes:encode编码
bytes-->str:decode解码

字符串通过编码成为字节码,字节码通过解码成为字符串。
其中encode() 和decode()方法可以接受参数,其声明分别是:
bytes.decode(encoding='utf-8',errors='strict')
str.encode(encoding='utf-8',errors='strict')
- 其中encoding指编码/解码使用的字符编码
- errors是指错误处理方案,默认为strict(严格的)意味着如果编码出现错误将会抛出UnicodeError
- 如果想忽略编码错误,可将errors设置为:ignore
绑定端口
sock.bind(("",9999))
方法接受一个参数,""中间是IP地址,空字符串指绑定本机所有网卡地址,9999为绑定的端口
案例:简单聊天室
import socket
udp_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
def main():
# 绑定端口
udp_socket.bind(("",9999))
while True:
operate = input('请输入操作编号:1发送,2接受,3退出')
if operate == '1':
print('选择发送')
sendmessage(udp_socket)
elif operate == '2':
print('选择接受:')
recvmessage(udp_socket)
else:
print('退出了')
break
def sendmessage(udp):
remote_addr = ("192.168.27.77",7979)
data = input('请输入数据')
udp.sendto(data.encode('GBK'),remote_addr)
def recvmessage(udp):
data,addr = udp.recvfrom(4*1024)
print("接收%s数据:%s" % (str(addr), data.decode('GBK')))
if __name__ == "__main__":
main()

TCP
传输控制协议,是一种面向链接的、可靠的,基于字节流的传输层通信协议。
特点
面向对象--通信之前必须先建立连接
可靠传输:
应答机制
超时重传
有序编号
校验机制
流量控制
TCP客户端流程
connect函数:创建和服务器之间的链接
参数:服务器套接字(IP,port)
recv函数:接受TCP数据,阻塞等待
参数:表示本次接收的最大长度
返回值两种作用
正常情况:接收到的是对方发给自己的数据<bytes数据>
如果收到数据是b'' 说明对方断开链接
send函数:发送TCP数据
参数:表示发送的数据<bytes类型>
返回值 成功发送的字节数
服务器流程
listen函数
变为被动套接字--接受到来自客户端的链接
accept函数
客户端关联的套接字,客户端地址 = accept()
阻塞等待,等待服务器取出一个客户端服务

2MSL状态
TCP规定,主动断开链接的一方,需要等待30s-2min,以确认最后一次ACK一定被对方接收到,导致了TCP链接使用过的端口在30s-2min之内,不能被重新再次绑定。
解决方案:sock.setsockopt()设置套接字选项
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
出现address in use问题的三种原因
1. pycharm同时启动了多个程序绑定同一个端口
2. pycharm 后台进程还在继续占用 之前的端口
3. TCP 2MSL时间
--- 设置套接字选项 并且 终端运行
# 忽略2MSL时间规定 可以让TCP服务器不用等待2MLS时间可以理解重新绑定 之前的端口
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
案例:文件传输
服务器:
# 导包
import socket
import time
# 创建套接字
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 绑定
server_socket.bind(('', 8989))
# 设置套接字
server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR, 1)
# 监听
server_socket.listen(128)
while True:
client_socket,client_addr = server_socket.accept()
print(client_addr, '链接了')
filename = client_socket.recv(4096).decode()
try:
with open(filename, 'rb') as f:
while True:
# 读文件
data = f.read(4096)
time.sleep(0.1)
if data:
count = client_socket.send(data)
print('读取数据长度:%d,发送数据长度:%d,读取到:%d' % (len(data),count,f.tell()))
else:
print('发送完毕,无数据')
break
except Exception as e:
print(e)
pass
客户端:
# 导包
import socket
# 创建套接字
tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 链接服务器
tcp_socket.connect(('192.168.27.26', 6666))
print('服务器链接成功')
# 接受文件名
filename = input('请输入文件路径')
# 发送文件名
count = tcp_socket.send(filename.encode())
if count:
print('文件名发送成功')
# 循环接受数据
while True:
with open('下载--' + filename, 'ab') as f:
data = tcp_socket.recv(4096)
if data:
print('接受到数据,长度为:', len(data))
f.write(data)
else:
print('传输完毕')
break
print('接受完成')
TCP注意点:
- TCP服务器一般情况下需要绑定,否则客户端找不到这个服务器。
- tcp客户端一遍不绑定,因为是主动链接客户端服务器,所以只要确定好服务器的IP,port等信息就好,本地客户端可以随机。
- tcp服务器中通过listen可以将socket创建出来,主动套接字变为被动的,这是做tcp服务器时必须要做的。
- 当客户端需要链接服务器时,就需要使用connect进行链接,udp是不需要链接的,而是直接发送,但是tcp必须先链接,只有链接成功才能通信。
- 当一个tcp客户端连接服务器时,服务器端会有1个新的套接字,这个套接字用来标记这个客户端,单独为这个客户端服务。
- listen后的套接字是被动套接字,用来接收新的客户端的链接请求,而accept返回的新套接字是标识这个新客户端的
- 关闭listen后的套接字意味着被动套接字关闭了,会导致新的客户端不能够链接服务器,但是之前已经链接成功的客户端正常通信。
- 关闭accept返回的套接字意味着这个客户端已经服务完毕。
- 当客户端的套接字调用close后,服务器会recv解阻塞,并且返回的长度为0,因此服务器可以通过返回数据的长度来区别客户端是否已经下线,同理当服务器断开tcp链接的是偶,客户端同样也会收到0字节的数据。
本文详细介绍了IP地址的不同分类及其应用,包括A类至E类地址的特点与范围,私有IP地址的规定,以及如何利用ifconfig/ipconfig、ping等工具进行网络诊断。此外还深入探讨了端口的概念,知名端口与动态端口的区别,进程间通信的实现方式,并通过Python示例展示了如何创建Socket进行UDP与TCP通信。
529

被折叠的 条评论
为什么被折叠?



