socket套接字编程
-
套接字:实现网络编程进行数据传输的一种技术手段
-
python实现套接字编程
import socket
-
套接字类型
流式套接字(SOCK_STREAM):以字节流的方式进行数据传输,实现TCP网络传输方案。
数据报套接字(SOCK_DGRAM): 以数据报形式传输数据,实现UDP网络传输方案。
面向连接-tcp协议-可靠地-流式套接字
面向无连接-udp协议-不可靠-数据报套接字
TCP套接字编程
- 服务端流程
-
创建套接字对象
sockfd = socket.socket(socket_family=AF_INET, socket_type = SOCK_STREAM, proto = 0)
功能: 创建套接字对象
参数:socket_family 网络地址类型 AF_INET==>IPv4 socket_type 套接字类型 SOCK_STREAM 流式 SOCK_DGRAM 数据报 proto 子协议选择,通常为0 返回值: 套接字对象
-
绑定地址
sockfd.bind(addr) 功能: 绑定本机网络地址 参数: 元组,(ip,port) ('0.0.0.0',8888)
-
设置监听
sockfd.listen(n) 功能:将套接字设置为监听套接字,创建监听队列 参数:监听队列大小
-
等待处理客户端请求
connfd,addr = sockfd.accept() 功能:阻塞等待处理客户端请求 返回值:connfd 客户端连接套接字 addr 连接的客户端地址
阻塞函数:
程序运行过程中遇到阻塞函数则暂停执行,直到达到某种条件后继续运行。
-
收发消息
data = connfd.recv(buffersize) 功能: 接收客户端消息 参数:每次最多接收消息的大小 返回值:收到的消息内容 n = connfd.send(data) 功能:发送消息 参数:要发送的内容 bytes格式 返回值:发送了多少字节 * str --> bytes string.encode() * bytes --> str bytes.decode()
-
关闭套接字
sockfd.close() 功能: 关闭套接字
-
服务端代码块实例:
# tcp_server.py import socket # TCP创建套接字 sockfd = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 绑定地址 sockfd.bind(('0.0.0.0',8888)) # 设置监听 sockfd.listen(3) # 等待客户端连接 print("Waiting for connect ....") connfd,addr = sockfd.accept() print("Connect from",addr) # 客户端地址 # 消息收发 data = connfd.recv(1024) print("Receive message:",data.decode()) n = connfd.send(b"Receive your message") print("Send %d bytes"%n) # 关套接字 connfd.close() sockfd.close()
-
客户端流程
-
创建套接字
*只有相同类型套接字才可以通信 -
请求连接
sockfd.connect(addr) 功能: 连接服务端 参数: 元组, 服务端地址
-
消息收发
*消息的收发要配合 -
关闭套接字
-
客户端代码块实例:
# tcp_client.py from socket import * # 创建套接字 sockfd = socket() # 发起连接 server_addr = ('127.0.0.1',8888) sockfd.connect(server_addr) # 收发消息 data = input(">>") sockfd.send(data.encode()) # 转换为字节串 data = sockfd.recv(1024) print("From server:",data.decode()) #关闭套接字 sockfd.close()
-
一、TCP套接字传输特点
1.tcp连接中当一端退出,另一端如果阻塞在recv,则recv会立即返回一个空子串
2.tcp连接中如果另一端已经不存在,在试图使用send向其发送内容时会出现BrokenPipe(通道破坏) -
二、网络收发缓冲区
1.缓冲区有效的协调了消息的收发速度
2.send,recv,实际是向缓冲区发送接收消息,当缓冲区不为空的时候,reccv就不会阻塞 -
三、粘包问题
原因:tcp以字节流方式传输数据,没有消息边界,多次发送的内容如果被一次接收就会形成粘包影响:如果每次发送的内容是需要独立解析的含义,此时粘包会对消息解析产生影响
处理:
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目标地址
-
关闭套接字
-
服务端代码:
# udp_server.py 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("收到来自%s的消息:%s"%(addr,data.decode())) sockfd.sendto(b"shoudao",addr) # 关闭套接字 sockfd.close()
-
客户端流程
-
创建UDP套接字
sockfd = socket(AF_INET,SOCK_SGRAM)
-
发送接收消息
-
关闭套接字
-
UDP套接字客户端代码
# udp_client.py from socket import * # 服务端地址 HOST = "127.0.0.1" PORT = 8888 ADDR = (HOST,PORT) # 创建套接字 sockfd = socket(AF_INET,SOCK_DGRAM) # 收发消息 while True: data = input("==>:") if not data: break sockfd.sendto(data.encode(),ADDR) msg,addr = sockfd.recvfrom(1024) print("来自:",msg.decode()) sockfd.close()
-
总结:
tcp套接字和udp套接字编程区别1.流式套接字以字节流方式传输数据,数据报套接字以数据报形式传输 2.tcp套接字会有粘包问题,udp套接字由消息边界不会粘包 3.tcp套接字保证消息的完整性,udp不保障 4.tcp套接字依赖listen accept完成连接才能进行数据收发,udp套接字不需要 5.tcp使用send recv 收发消息,udp使用sendto recvfrom
-
socket模块方法和socket套接字属性
-
部分socket模块方法
socket.gethostname() #显示主机名称 soccket.gethostbyname("www.baidu.com") #根据主机名获取IP地址。 socket.getservbyname("mysql") #根据服务获取监听端口 soclet.getservbyport(3306) #根据端口获取服务名称 socket.inet_aton("192.168.1.2") #将IP地址转换为字节串 socket.inet_ntoa(b'\xc0\xa8\x01\x01') #将字节串转换为IP地址
-
套接字属性
-
socket.family 地址类型
-
socket.type 套接字类型
-
socket.getsockname() 绑定地址
-
socket.fileno() 获取文件描述符
文件描述符:系统中么一个IO操作都会分配一个整数作为编号,该整数即这个IO文件描述符 特点:每个IO的文件描述符不会重复
-
getpeername() 获取套接字绑定地址
-
setsockopt(leve1,option,value)
功能:设置套接字选项 参数:level选项类别 SOL_SOCKET option 具体选项内容 value 选项值
-
-
-
UDP套接字广播
广播定义:一端发送,多端接收
广播地址:每个网段内的最大地址,向该地址发送,则网段内所有的主机都能接收from socket import * from time import sleep dest = ("0.0.0.0",5555) s = socket(AF_INET,SOCK_DGRAM) # 设置可以发送接受广播 s.setsockopt(SOL_SOCKET,SO_BROADCAST,True) data = ''' ********************** 4.4 清明前 春风十里不如你 000; ********************** ''' while True: sleep(2) s.sendto(data.encode(),dest)
# broadcast_recv.py from socket import * # 创建套接字 s = socket(AF_INET,SOCK_DGRAM) s.setsockopt(SOL_SOCKET,SO_BROADCAST,True) s.bind(("127.0.0.1",5555)) while True: msg, addr = s.recvfrom(1024) print(msg.decode())
- 利用TCP完成文件的传输
######服务端###############
from socket import *
s = socket()
s.bind(('127.0.0.1',8888))
s.listen(3)
c,addr = s.accept()
print("Connect from",addr)
f = open('p.jpeg','wb')
while True:
data = c.recv(1024)
if not data:
break
f.write(data)
f.close()
c.close()
s.close()
#########发送端#############
from socket import *
s = socket()
s.connect(('127.0.0.1',8888))
#自己设定的图片
f = open('timg.jpeg','rb')
while True:
data = f.read(1024)
if not data:
break
s.send(data)
f.close()
s.close()