目录
套接字介绍
- 套接字:实现网络编程进行数据传输的一种技术手段
- Python实现套接字编程:import socket
- 套接字分类:
- 流式套接字(SOCK_STREAM):以字节流方式传输数据(可以理解为像水流一样传输),实现tcp网络传输方案。(面向连接–tcp协议–可靠的–流式套接字)
- 数据报套接字(SOCK_DGRAM):以数据报形式传输数据(可以理解为像一瓶一瓶的水一样传输),实现udp网络传输方案。(无连接–udp协议–不可靠–数据报套接字)
TCP套接字编程
服务端流程
socket表示创建一个套接字(买了一个电话)
bind用于绑定主机ip地址等信息(好比办了一张电话卡)
listen设置监听,可以被其他套接字或程序连接的功能(充话费)
accept处于等待状态(让电话处于待机状态)
send/recv发送/接收(用电话)
close销毁套接字(把电话摔了)
- 创建套接字
sockfd=socket.socket(socket_family=AF_INET,socket_type=SOCK_STREAM,proto=0)
功能:创建套接字
参数:socket_family 网络地址类型 :AF_INET表示ipv4(默认值)、AF_INET6表示ipv6
socket_type 套接字类型: SOCK_STREAM表示流式(默认值)、SOCK_DGRAM表示数据报
proto 通常为0 ,选择子协议(一般用不上)
返回值:套接字对象
- 绑定地址
sockfd.bind(addr)
功能:绑定本机网络地址
参数:二元元祖(ip,port)。比如:(‘0.0.0.0’,8888)
- 设置监听
sockfd.listen(n)
功能:将套接字设置为监听套接字,确定监听队列的大小
参数:监听队列大小(linux下固定的)
- 等待处理客户端连接请求
connfd, addr = sockfd.accept()
功能:阻塞等待处理客户端请求
返回值:connfd 客户端连接套接字(为每个客户端创建一个套接字),addr 连接的客户端地址
- 消息收发
data = connfd.recv(buffersize)
功能:接收客户端消息
参数:每次最多接收消息的大小(单位:字节)
返回值:接收到的内容
n = connfd.send(data)
功能:发送消息
参数:要发送的内容,bytes格式(字节串)
返回值:发送的字节数
- 关闭套接字
connfd.close()
sockfd.close()
功能:关闭套接字
重点代码:
'''
TCP 套接字服务端重点代码
'''
import socket
# 创建流式套接字
sockfd=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 绑定本机地址
sockfd.bind(('0.0.0.0', 8888))
# 设置监听
sockfd.listen(5)
# 等待客户端连接
print('Waiting for connect...')
connfd, addr = sockfd.accept()
# 收发消息
data = connfd.recv(1024)
print('接收到的消息: ', data.decode())
n = connfd.send(b'Receive your message')# 注意发送字节串,也可以encode
print('发送了%d个字节数据' % n)
# 关闭套接字
connfd.close()
sockfd.close()
客户端流程
-
创建套接字
注意:只有相同类型的套接字才能进行通信 -
请求连接
sockfd.connect(server_addr)
功能:连接服务器
参数:元祖 server_addr =(服务器地址,端口号)
-
收发信息
注意:防止两端都阻塞,recv send要配合(一收一发,或者一发一收) -
关闭套接字
重点代码:
from socket import *
# 创建tcp套接字
sockfd = socket()#此处如果是import socket方式,就和上述
# 发起连接
server_addr = ('XXX.XXX.XXX.XXX', 8888) # 服务端的网络地址
sockfd.connect(server_addr)
# 收发消息
sockfd.send('来自客户端的消息'.encode())
data = sockfd.recv(1024)
print('From Server:', data.decode())
# 关闭
sockfd.close()
tcp套接字数据传输特点
- tcp连接中当一端退出,如果另一端堵塞在recv,此时recv会立即返回一个空字符串
- tcp连接中如果一端已经不存在,仍然试图通过send发送则会产生BrokenPipeError
- 一个监听套接字可以同时监听多个客户端,也能够重复被连接
网络收发缓冲区
- 网络缓冲区有效协调了消息的收发速度
- send和recv实际是向缓冲区发送接收消息,当缓冲区不为空recv就不会阻塞。
tcp粘包
- 原因:tcp以字节流方式传输,没有消息边界。多次发送的消息被一次接收,此时就会形成粘包。(通俗来说,就是发送方发的太快了,接收方收的太慢了,同时接收方发的慢,发送方收太快,造成粘包。比如发送方一次发送15字节,接收方一次从缓冲区接收5字节,接收方就返回三次receive message到发送方的缓冲区,但是发送方接收还比较快,一次性把这三次receive message全接收了,造成粘包。)
- 影响:如果每次发送内容是一个独立的含义,需要接收端独立解析,此时粘包有会影响。(文件、音频、视频下载没什么影响)
- 处理方法:1. 人为的添加消息边界;2. 控制发送速度
UDP套接字编程
服务端流程
- 创建数据报套接字
sockfd = socket(AF_INET, SOCK_DGRAM)
- 绑定地址
sockfd.bind(addr)
- 消息收发
data, addr = sockfd.recvfrom(buffersize)
功能:接收UDP消息
参数:每次最多接收多少字节
返回值:data 接收到的内容;addr消息发送方的地址
n=sockfd.sendto(data,addr)
功能:发送UDP消息
参数:data 发送的内容(bytes格式);addr 目标地址
返回值:发送的字节数
- 关闭套接字
sockfd.close()
重点代码:
'''
UDP 套接字服务端重点代码
'''
from socket import *
# 创建数据报套接字
sockfd = socket(AF_INET, SOCK_DGRAM)
# 绑定地址
server_addr = ('0.0.0.0', 8888)
sockfd.bind(server_addr)
# 收发消息
while True:
data, addr = sockfd.recvfrom(1024)
print("收到的消息:",data.decode())
sockfd.sendto(b'Thanks',addr)
# 关闭套接字
sockfd.close()
客户端流程
- 创建套接字
- 收发消息
- 关闭套接字
重点代码
'''
UDP 套接字客户端重点代码
'''
from socket import *
# 服务器地址
HOST = '127.0.0.1'
PORT = 8888
ADDR = (HOST, PORT)
# 创建套接字
sockfd = socket(AF_INET, SOCK_DGRAM)
# 收发消息
while True:
data = input('Msg>>')
if not data:
break
sockfd.sendto(data.encode(), ADDR)
msg, addr = sockfd.recvfrom(1024)
print('From server:', msg.decode())
sockfd.close()
总结(tcp套接字和udp套接字编程区别)
- 流式套接字是以字节流方式传输数据,数据报套接字是以数据报形式传输
- tcp套接字会有粘包,udp套接字有消息边界不会粘包
- tcp套接字保证消息的完整性,udp则不能
- tcp套接字依赖listen accept建立连接才能收发消息,udp套接字不需要
- tcp套接字使用send,recv收发消息,udp套接字使用sendto,recvfrom
补充(socket模块方法和socket套接字属性)
此部分了解即可
- 部分socket模块方法(socket.方法名)
- gethostname() 获取计算机名
- gethostbyname(‘www.baidu.com’) 获取主机ip地址
- getservbyname(‘mysql’) 获取服务端口号
- getservbyport(3306)
- inet_aton(‘192.168.1.2’) 将IP地址转换为bytes字节串
- inet_ntoa(b’\xc0\xa8\x01’)将bytes字节串转换为IP地址
- 套接字属性
- sockfd.type 套接字类型
- sockfd.family 套接字地址类型
- sockfd.getsockname() 获取套接字绑定地址
- sockfd.fileno() 获取套接字的文件描述符
- connfd.getpeername() 获取连接套接字客户端地址(连接套接字调用)
- sockfd.setsockopt(level,option,value) 设置套接字选项,level 选项类别;option 具体选项内容;value 选项值(比如:设置套接字端口立即重用,放在创建套接字的下面:sockfd.setsockopt(SOL_SOCKET, SO_REUSEADDR, True) )
- sockfd.getsockopt(level,option) 获取套接字选项值,返回值为value
网络编程TCP、UDP代码已上传,欢迎大家下载、学习、交流,资源地址:https://download.csdn.net/download/xiecheng1995/12182529
来源:CSDN
作者:酷酷的橙007
链接:https://blog.csdn.net/xiecheng1995/article/details/104408485