TCP、UDP套接字网络协议
TCP服务端(以字节串传输信息)
import socket
1、创建套接字
sockfd = socket.socket(socket_family = AF_INET,socket_type = SOCK_STREAM,proto = 0)
功能:创建一个IPv4的流式套接字,括号中的创建IPv4流式套接字的时候可以不写,有缺省值。
参数:socket_family 地址族类型 AF_INET 表示IPv4网络通信
socket_type 套接字类型 SOCK_STREAM 流式 SOCK_DGRAM 数据报
proto 通常为0(选择子协议)
返回值:返回一个套接字对象
2、绑定IP端口
sockfd.bind(("IP地址",端口号))
功能:绑定IP地址和端口号
参数:二元元组
3、将套接字设置为可监听
sockfd.listen(n)
功能:将套接字设置为监听套接字,并创建监听队列(只有是监听套接字,才可以连接客户端)
参数:监听对象的大小 n为大于0的正整数
一个监听套接字可以连接多个客户端
4、等待客户端的连接
connfd,addr = sockfd.accept()
功能:阻塞等待客户端连接,返回客户端的套接字和地址元组
返回值:connfd 一个新的套接字,用于和客户端通信
addr 连接的客户端的地址(元组)(ip,port)
阻塞函数:当程序运行到阻塞函数位置,如果某种预期条件没有达成则暂停继续运行,直到条件达成在继续运行
5、消息接收和发送
data = connfd.recv(buffersize)
data为connfd套接字接收到的消息,以字节方式进行传输
n = connfd.send(b'adsfafef')
n为发送的字节数
功能:发送消息
参数buffersize:每次最多接收的消息大小 bytes
connfd.sent(b'hello woeld')返回值是发送的字节数
6、关闭套接字
close()
功能:关闭套接字,tcp连接断开
telnet ip port 表示连接tcp服务端
import socket sockfd = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 创建tcp套接字 sockfd.bind(('0.0.0.0', 8888)) # 绑定地址 sockfd.listen(5) # 设置监听 print("Waiting for connect...") # 阻塞等待处理连接 connfd, addr = sockfd.accept() # 等待客户端连接 print("Connect from", addr) # 打印链接的客户端地址 data = connfd.recv(1024) # 接收消息 print("收到:", data) n = connfd.send(b'over') # 发送字节串 print("发送%d字节" % n) # 关闭套接字 connfd.close() sockfd.close()
TCP客户端(以字节串传输信息)
1.创建套接字
socket()
* 通信的两端套接字类型相同
2. 发起连接
sockfd.connect(("IP地址",端口号))
功能 : 发起连接请求
参数 : 元组,服务器端的地址
3.发收消息
sockfd.send(字节串内容)
sockfd.recv() # 接收到的是字节串内容
* 两端收发需要配合
4.关闭套接字
close()
from socket import * sockfd = socket() # 创建套接字,TCP协议不用填写缺省值 sockfd.connect(("176.122.1.61",8888)) # 发起请求连接IP地址176.122.1.61,端口8888的主机 data = input("发送:") # 输入要发送的信息 sockfd.send(data.encode()) # 发送字节串内容 d = sockfd.recv(1024).decode() # 接收到的是字节串内容 print("接收到:", d) sockfd.close()
UDP服务器
UDP是无连接的, 不用accetp和listen
1、创建套接字----》数据报套接字
sockfd = socket(AF_INET,SOCK_DGRAM)
2、绑定服务端地址
sockfd.bind()
3、消息的收发
data,addr = sockfd.recvfrom(buffersize)
功能:接收udp消息
参数:每次最多接受消息大小
返回值:data 接收到的消息 addr 消息发送者的地址(IP号和端口号)
sockfd.sendto(data,addr)
功能:udp发送消息
参数:data要发送的消息 bytes
addr 客户端地址(地址包括IP和端口号)
返回值:发送的字节
每次接收一个报文,如果没有接收完全则丢弃没有收到的内容
4、关闭套接字
sockfd.close()
""" UDP 套接字服务端""" from socket import * sockfd = socket(AF_INET, SOCK_DGRAM) # 创建套接字 sockfd.bind(('127.0.0.1', 8888)) # 绑定地址 # 收发消息 while True: data, addr = sockfd.recvfrom(1024) print("收到的消息:", data.decode()) sockfd.sendto(b'Receive', addr) sockfd.close() # 关闭套接字
UDP客户端
1、创建套接字
sockfd = socket(AF_INET,SOCK_DGRAN)
2、消息收发
收:data,addr = sockfd.recvfrom(buffersize)
发:sockfd.sendto(data,addr)
data,addr = sockfd.recvfrom(1024)
sockfd.sendto(data.encode(), ("192.168.191.3",8888))
3、关闭套接字
sockfd.close()
from socket import * import sys # 命令行输入服务器地址 if len(sys.argv) < 3: print(''' argv is error !! 请在终端输入 python3 udp_client.py 127.0.0.1 8888 ''') raise HOST = sys.argv[1] PORT = int(sys.argv[2]) ADDR = (HOST,PORT) sockfd = socket(AF_INET,SOCK_DGRAM) # 创建套接字 while True: data = input("消息:") if not data: # 如果收到空消息则退出 break sockfd.sendto(data.encode(),ADDR) data,addr = sockfd.recvfrom(1024) print("从服务端收到:",data.decode()) sockfd.close()
补充: sys.argv
功能:获取来自命令行的参数,形成一个列表
以空格作为每一项分隔,如果一项中有空格则用引号表示一个整体
命令行内容作为字符串传入
TCP流式套接字和UDP数据报套接字区别
1、流式套接字采用字节流的方式传输数据,而数据报套接字以数据报形式传输
2、TCP会产生粘包现象,UDP消息是有边界的不会粘包
3、TCP传输是建立在连接的基础上,保证传输的可靠性,而UDP一次接收一个数据报,不保证完整性
4、TCP需要依赖listen、accept建立连接,UDP不用
5、TCP收发消息使用recv、send、sendall。UDP使用recvfrom、sendto
UDP应用之广播
一点发送多点接收
目标地址:广播地址,每个网段类最大的地址
172.60.50.255 ----》<broadcast>
广播接收
from socket import * s = socket(AF_INET,SOCK_DGRAM) # 创建一个数据报套接字 s.setsockopt(SOL_SOCKET,SO_BROADCAST,1) # 设置为可以接收广播 s.bind(('0.0.0.0',9999)) # 绑定IP地址 while True: try: msg,addr = s.recvfrom(1024) print("从{}获取信息:{}".format(addr,msg.decode())) except KeyboardInterrupt: print("接收消息结束") break except Exception as e: print(e) s.close()
广播发送
from socket import * from time import sleep dest = ('192.168.191.3',9999)# 设置广播地址 s = socket(AF_INET,SOCK_DGRAM) # 创建一个数据报套接字 s.setsockopt(SOL_SOCKET,SO_BROADCAST,1) #设置套接字可以发送接受广播 while True: sleep(1) s.sendto("我叫凌逆战!".encode(),dest) s.close()