网络编程
Ubuntu命令
查看ip: ifconfig
ping 查看网络连通性
ping 127.0.0.1 检查网络功能是否正常
ping 本机网卡IP地址 检查网卡是否正常工作
ping 远程主机IP/域名 检查与远程主机的连通性
端口基础
定义:系统分配给网络应用程序的编号,用来区分数据传输
网络程序必须要有端口号
知名端口号0-1023
动态端口号 1024-65535
检验指定端口网络连接情况:netstat -an | grep ":8080"
列出当前系统端口所对应的程序: lsof -i [tcp/udp]:8080
扩展: netstat -anp | grep ":8080" 查看指定端口的程序网络连接情况
扩展: ps -aux | grep "python" 查看python的程序
扩展: kill -9 进程的PID 关闭进程
UDP
特点
- 无需确认对端是否存在,发送端随时可发送数据
- 无连接、资源开销小、速度块、单个数据包最大为64K
- 传输不可靠,容易丢失数据
- 没有流量控制,所有接受方需及时接收数据,否则会出现缓冲过慢,电脑卡死
使用场景
- 音乐视频传输
- 广播
- 主要用在通讯质量要求不高的场景
创建步骤
客户端:初始化,指定ip端口sendto发送,recvform接受,close关闭
#创建一个udp_licent #初始化,ipv4,指定udp模式,绑定端口 #发送数据 #接受数据 #关闭套接字对象 import socket import time def main(): #初始化 udp_licent = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) #发送数据 udp_licent.sendto("要发送的数据".encode("utf-8"),('127.0.0.1',8080)) #接受数据 info = udp_licent.recvfrom(1024) # 每次接受1024个字节数据 print(info[0].decode("utf-8")) info = udp_licent.recvfrom(1024) #每次接受1024个字节数据 print(info[0].decode("utf-8")) # 接受到的数据为二进制数据进行解码 #关闭对象 udp_licent.close() time.sleep(1) if __name__ == '__main__': while True: main()
服务端:初始化、端口复用、绑定端口、广播模式、接受、发送(广播模式255地址进行广播)、关闭#创建一个udp_server #初始化 #复用端口 #绑定端口 #设置广播模式 #响应客户端 #接受数据 #发送数据 #关闭套接字 import socket def main(): #初始化 udp_server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) #复用端口 udp_server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True) #设置广播模式,发送时指定255.255.255.255 udp_server.setsockopt(socket.SOL_SOCKET,socket.SO_BROADCAST,True) #绑定端口 udp_server.bind(('',8080)) #接受数据,收到数据为一个元组,0下标元素为数据,1号下标为发送者地址与端口 info = udp_server.recvfrom(1024) #每次接受1024个字节数据 #接受数据时阻塞程序 print(".............程序被阻塞.................") #发送者地址信息 news="收到:%s"%info[0].decode("utf-8") print(news) #发送数据,使用接受到的信息可以给发送者回复 udp_server.sendto(news.encode("utf-8"),info[1]) #使用255.255.255.255地址可以进行广播发送,此时简写成发送者的端口 #实际进行广播时,客户端要设置成与客户端广播一致的端口 udp_server.sendto("进行广播".encode("utf-8"),('255.255.255.255',info[1][1])) #关闭服务器套接字 udp_server.close() if __name__ == '__main__': while True: main()
TCP
概述
- 面向连接的、可靠的、基于字节流的传输层通信协议.
特点
- TCP通信需要经过创建连接、数据传送、终止连接三个步骤。
- 先建立连接才可以进行数据传输,双方都必须为该连接分配必要的系统内核资源,以管理连接的状态和连接上的传输可靠传输,采用发送应答机制,超时重传,错误校验,流量控制和阻塞管理
创建步骤
客户端:初始化、connect连接、send发送、recv接受,close关闭
import socket # 创建tcp socket tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 目的信息 server_ip = input("请输入服务器ip:") server_port = int(input("请输入服务器port:")) # 链接服务器 tcp_client_socket.connect((server_ip, server_port)) # 提示用户输入数据 send_data = input("请输入要发送的数据:") tcp_client_socket.send(send_data.encode("gbk")) # 接收对方发送过来的数据,最大接收1024个字节 recvData = tcp_client_socket.recv(1024) print('接收到的数据为:', recvData.decode('gbk')) # 关闭套接字 tcp_client_socket.close()
服务端:初始化、端口复用、绑定端口、监听模式、建立连接生成服务对象、服务对象send发送、服务对象recv接受、关闭服务 对象、关闭服务端import socket # 创建socket tcp_server_socket = socket(socket.AF_INET, socket.SOCK_STREAM) # 本地信息 address = ('', 7788) # 绑定 tcp_server_socket.bind(address) # 设置监听 # 使用socket创建的套接字默认的属性是主动的,使用listen将其变为被动的,这样就可以接收别人的链接了 # 128:表示最大等待连接数 tcp_server_socket.listen(128) # 如果有新的客户端来链接服务器,那么就产生一个新的套接字专门为这个客户端服务 # client_socket用来为这个客户端服务 # tcp_server_socket就可以省下来专门等待其他新客户端的链接 client_socket, clientAddr = tcp_server_socket.accept() # 接收对方发送过来的数据 recv_data = client_socket.recv(1024) # 接收1024个字节 print('接收到的数据为:', recv_data.decode('gbk')) # 发送一些数据到客户端 client_socket.send("thank you !".encode('gbk')) # 关闭为这个客户端服务的套接字,只要关闭了,就意味着为不能再为这个客户端服务了,如果还需要服务,只能再次重新连接 client_socket.close()
UDP和TCP的区别
- TCP面向连接不支持广播,UDP不是面向连接支持广播式
- TCP需要连接,提供可靠数据传输且按序到达,但传输速度慢,UDP不需要连接,不保证可靠传输,但速度快
- TCP适合发送大量数据,有流量控制,UDP适合发少量数据,没有流量控制
文件下载器示例代码
TCP服务端 参考代码如下:
import socket
import os
if __name__ == '__main__':
# 创建tcp服务端socket
tcp_serve_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置socket选项,防止程序退出端口不立即释放的问题
tcp_serve_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 绑定端口
tcp_serve_socket.bind(("", 9090))
# 设置监听,把主动套接字改成被动套接字,被动套接字只能接收客户端的连接请求,不能收发消息
tcp_serve_socket.listen(128)
# 循环接收客户端的连接请求, 提示:现在的下载是同步下载,一个用户下载完成以后另外一个用户才能下载
while True:
# 接收客户端的连接请求
service_client_socket, ip_port = tcp_serve_socket.accept()
# 代码执行到说明解阻塞,说明连接建立成功
file_name_data = service_client_socket.recv(1024)
# 解码数据
file_name = file_name_data.decode("gbk")
print(file_name, ip_port)
if os.path.exists(file_name):
# 文件存在
with open(file_name, "rb") as file:
# 读取文件数据
while True:
file_data = file.read(1024)
if file_data:
# 发送文件数据给客户端
service_client_socket.send(file_data)
else:
break
else:
print("文件不存在")
# 终止和客户端服务
service_client_socket.close()
# 终止提供处理连接请的服务
tcp_serve_socket.close()
TCP客户端 参考代码如下:
import socket
if __name__ == '__main__':
# 创建tcp客户端socket
tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 建立连接
tcp_client_socket.connect(("192.168.107.160", 9090))
# 获取用户输入文件名
file_name = input("请输入您要下载的文件名:")
# 使用gbk进行编码
file_name_data = file_name.encode("gbk")
# 代码执行到此,说明连接建立成功
tcp_client_socket.send(file_name_data)
with open("/home/python/Desktop/" + file_name, "wb") as file:
# 循环接收服务端发送的文件二进制数据
while True:
# 获取服务端文件数据
file_data = tcp_client_socket.recv(1024)
if file_data:
# 写入到指定文件
file.write(file_data)
else:
break
# 关闭socket
tcp_client_socket.close()