Socket:提供给程序可以对外进程连接的接口,是对底层协议的封装。根据不同的的底层协议,Socket的实现是多样化的。每个socket都要绑定端口号和IP
优势:在用python进行编程的时候不用考虑三次握手等网络协议的具体实现,可以直接通过Socket对象实现
创建Socket
语法:
s = socket.socket(AddressFamily, Type)
#Address Family:可以选择AF_INET(用于 Internet 进程间通信)或者AF_UNIX(用于同一台机器进程间通信),实际工作中常用AF_INET。
#Type:套接字类型,可以是SOCK_STREAM(流式套接字,主要用于TCP协议)或者SOCK_DGRAM(数据报套接字,主要用于UDP协议)
Socket通信流程
基于TCP协议为例:首先客户端与服务端都需要创建Socket
服务器:
Socket() :创建Socket
Bind():绑定IP和端口号
Listen():监听端口
Accept():等待接收
Receive():接收数据
Send():函数发送数据
Close(): 关闭Socket
客户端:
Socket() :创建Socket
Connet(): 连接服务器对应服务器的Accept()函数,三次握手就是在这个过程中完成的
Send():函数发送数据
Receive():接收数据
Close(): 关闭Socket
Socket对象常用方法
方法名 | 描述 |
s.bind() | 绑定地址(host,port)到套接字, 在AF_INET下,以元组(host,port)的形式表示地址。 |
s.listen() | 开始TCP监听。backlog指定在拒绝连接之前,操作系统可以挂起的最大连接数量。该值至少为1,大部分应用程序设为5就可以了。 |
s.accept() | 被动接受TCP客户端连接,(阻塞式)等待连接的到来 |
s.connect() | 主动初始化TCP服务器连接,一般address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。 |
s.recv() | 接收TCP数据,数据以字符串形式返回,bufsize指定要接收的最大数据量。flag提供有关消息的其他信息,通常可以忽略。 |
s.send() | 发送TCP数据,将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于string的字节大小。 |
s.sendall() | 完整发送TCP数据。将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。 |
s.recvfrom() | 接收UDP数据,与recv()类似,但返回值是一个元组(data,address)。其中data是包含接收数据的字符串,address是发送数据的套接字地址。 |
s.sendto() | 发送UDP数据,将数据发送到套接字,address是形式为(ipaddr,port)的元组,指定远程地址。返回值是发送的字节数。 |
s.close() | 关闭套接字 |
TCP编程
实例:使用服务器向浏览器发送: Hellow Word
创建TCP服务器
# -*- coding:utf-8 -*-
import socket #导入socket模块
host = '127.0.0.1' #主机IP
port = 8080 #端口号
web = socket.socket() #创建 socket 对象
web.bind((host,port)) #绑定端口
web.listen(5) #设置最多连接数
print ('服务器等待客户端连接...')
#开启死循环
while True:
conn,addr = web.accept() #建立客户端连接:conn是一个新的Socket对象,addr是连接客户端的IP地址
data = conn.recv(1024).decode() #获取客户端请求数据,decode()指定解码格式
print(data) #打印接受数据
conn.sendall(b'HTTP/1.1 200 OK\r\n\r\nHello World') #向客户端发送数据
conn.close() #关闭链接
#############
##服务器等待客户端连接...
##hi
验证:
命令行启动此程序
浏览器访问:127.0.0.1:8080
创建TCP客户端
import socket # 导入socket模块
s= socket.socket() # 创建TCP/IP套接字
host = '127.0.0.1' # 获取主机地址
port = 8081 # 设置端口号
s.connect((host,port)) # 主动初始化TCP服务器连接
send_data = input("请输入要发送的数据:") # 提示用户输入数据
s.send(send_data.encode()) # 发送TCP数据,encode():指定编码格式
# 接收对方发送过来的数据,最大接收1024个字节
recvData = s.recv(1024).decode() #encode():指定解码格式
print('接收到的数据为:',recvData)
# 关闭套接字
s.close()
##############################
##请输入要发送的数据:hi
##接收到的数据为: HTTP/1.1 200 OK
##Hello World
验证:命令行先执行服务器程序在执行客户端程序
服务器与客户端交互
实例:制作简易聊天窗口
实现:客户端发送的内容在服务端打印,服务端发送的内容在客户端打印。在输入baibai时终端连接
服务端代码:
import socket # 导入socket模块
host = socket.gethostname() # 获取主机地址
port = 12345 # 设置端口号
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #创建TCP/IP套接字
s.bind((host,port)) # 绑定地址(host,port)到套接字
s.listen(1) # 设置最多连接数量
sock,addr = s.accept() # 被动接受TCP客户端连接
print('连接已经建立')
info = sock.recv(1024).decode() # 接收客户端数据
while info != 'byebye': # 判断是否退出
if info : #判断是否有内容
print('接收到的内容:'+info)
send_data = input('输入发送内容:') # 发送消息
sock.send(send_data.encode()) # 发送TCP数据
if send_data =='byebye': # 如果发送exit,则退出
break
info = sock.recv(1024).decode() # 接收客户端数据
sock.close() # 关闭客户端套接字
s.close() # 关闭服务器端套接字
客户端代码:
import socket # 导入socket模块
s= socket.socket() # 创建TCP/IP套接字
host = socket.gethostname() # 获取主机地址
port = 12345 # 设置端口号
s.connect((host,port)) # 主动初始化TCP服务器连接
print('已连接')
info = ''
while info != 'byebye': # 判断是否退出
send_data=input('输入发送内容:') # 输入内容
s.send(send_data.encode()) # 发送TCP数据
if send_data =='byebye': # 判断是否退出
break
info = s.recv(1024).decode() # 接收服务器端数据
print('接收到的内容:'+info)
s.close() # 关闭套接字
验证:
UDP编程
应用场景
语音广播
视频
聊天软件
TFTP(简单文件传送)
SNMP(简单网络管理协议)
RIP(路由信息协议,如报告股票市场、航空信息)
DNS(域名解释
实例:将摄氏温度转化为华氏温度
创建UDP服务器
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) #创建UDP套接字
s.bind(('127.0.0.1', 8888)) # 绑定地址(host,port)到套接字
print('绑定UDP到8888端口')
# 接收数据:最大接受1024字节
data, addr = s.recvfrom(1024)
data = float(data)*1.8 + 32 # 转化公式
send_data = '转换后的温度(单位:华氏温度):'+str(data)
print('Received from %s:%s.' % addr)
s.sendto(send_data.encode(), addr) # 发送给客户端
s.close() # 关闭服务器端套接字
验证结果
UDP通信的基本模型