python之socket模块
Posted Zaeton
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python之socket模块相关的知识,希望对你有一定的参考价值。
socket
前言
主要用于自己自学python后端的笔记
一、socket模块
Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
在这里主要学习利用socket完成TCP/IP通讯,首先需要生成两个对象,一个是客户端(client),一个是服务端(sever)。
1.服务端(sever)
步骤;
1.创建对象 .socket()
2.绑定ip地址与端口 .bind()
3.监听 .listen()
4.接收一个套接口接受的一个连接 .accept()
5.接收连接进来的数据 .recv()
6.发送连接进来的数据 .send()
代码如下:
import socket
server = socket.socket()
# 绑定要监控的界面
server.bind(("localhost", 6969))
# 监听
server.listen()
print("我要开始等电话了!")
while True:
# 等电话打进来
conn, adr = server.accept()
while True:
data = conn.recv(1024)
print("接收:", data)
if not data:
print("host is lost")
break
conn.send(data.upper())
server.close()
代码解释:
server = socket.socket() #生成一个服务端
server.bind((“localhost”, 6969))# 绑定要监控的界面,元祖形式(ip地址,端口号)
server.listen() # 监听端口状态
conn, adr = server.accept() # 获取进来的对象是谁(conn),cnn为后数据传输通道,adr为ip地址
data = conn.recv(1024) # 接收数据,接收数据量为1024
conn.send(data) # 发送数据,需要编码endcode()
2.客户端(client)
步骤;
1.创建对象 .socket()
2.连接ip地址与端口 .connet()
3.接收进来的数据 .recv()
4.发送数据 .send()
代码如下:
import socket
client = socket.socket()
client.connect(('localhost', 6969))
while True:
msg = input(">>:")
if len(msg) == 0: continue
client.send(msg.encode("utf-8"))
data = client.recv(1024)
print("数据:", data)
client.close()
代码解释:
client.connect((‘localhost’, 6969)) # 设置IP地址和端口,元组形式
3.数据格式问题
python默认数据格式为Unicode,在发送数据时,函数send()的参数类型是:Byte,需要将数据转换类型。
4.数据沾包
当连续的调用send()时,接收recv()有大小限制,发送的数据量大于接收的数据量,截断的数据储存在缓存器BUFF中,下一次数据在传输时,会优先传输上次截断的数据,从而发生了粘包。
为了避免这种错误,通过设计反馈,即发送数据后反馈给发送数据回来。发送中间夹杂着一次接收,避免了数据在缓冲中导致粘包。
5.数据完整接收
数据接收recv()有大小限制,在为了保证目标数据的完整性,数据发送前应当给客户端发送数据量大小,用于判断数据是否接收完全。但如果两次send()连续执行会产生粘包。
二、socketsever模块
socketserver本质是基于socket模块进行的一个封装,将多线程并发功能集成到一个新的模块里,就叫socketserver;它用来解决TCP套接字无法并发的问题,也就是无法一个服务端不能同时服务多个客户端的问题(UDP没有此问题,因为它不需要链接)。
socketserver中包含了两种类,一种为服务类(server class),一种为请求处理类(request handle class)。
2.1 server类:处理链接
BaseServer 处理链接必须
TCPServer 处理流式(TCP)链接
UDPServer 处理数据报式(UDP)链接
2.2 request类:处理通信
BaseRequestHandler 处理通信
StreamRequestHandler 处理流式通信,即TCP
DatagramRequestHandler 处理数据报式通信,即UDP
2.3 socketsever服务端实现
步骤:
1、创建一个类,必须继承socketserver.BaseRequestHandler类
2、在该类中定义handle方法,其中self.request是获取的链接,self.client_address则是获取的地址
3.self.request.sendall(data) # 将受到的数据完整发送出去,返回none。
import socketserver
# 定义一个类,该类必须继承socketserver下的BaseRequestHandler类
class MyServer(socketserver.BaseRequestHandler):
def handle(self): # 必须定义一个handle方法
print('conn is ', self.request) # self.request是获取的链接,相当于conn
print('addr is ', self.client_address) # self.client_address则是获取的地址,相当于addr
# 循环收发消息
while True:
try: # 异常处理
# 收消息
data = self.request.recv(1024) # 1024字节
if not data: continue # 如果是空就重新输入
print('客户端发来的消息是:', data.decode('utf-8'), '\\n')
# 发消息
self.request.sendall(data.upper()) # 将受到的数据转化为大写后发回客户端
except Exception as e:
print(e) # 打印错误
break
if __name__ == '__main__':
host, port = 'localhost', 6969
# 再将这样的功能实例化成一个对象sever
# 第一个参数为服务端的ip地址,用元组传进;第二个参数是刚刚定义的那个类
sever = socketserver.TCPServer((host, port), MyServer)
sever.serve_forever() # 永远,就是通信循环(链接循环)
多线程使用socketsever…ThreadingTCPServer,即可实现多线程通讯。
以上是关于python之socket模块的主要内容,如果未能解决你的问题,请参考以下文章