Python篇-Socket网络编程
TZ:多读英文,少点烦躁
一 : 科普一分钟
简单来说Socket
就是对TCP/IP
等网络协议的封装和应用,其重要的两个动作就是发送
和接受
当我们需要调用网络连接时只需建立Socket
连接,Socket
需要知道目标计算机的IP地址
和端口号
,再指定协议类型即可。
二: Socket创建客户端与服务端
- 客户端
1.导入socket
模块
import socket
2.创建实体类,发送数据,端口号的作用是连接后具体指定哪个程序响应
#声明 socket 类型,同时生成socket连接对象
client = socket.socket()
#连接ip地址和端口号
client.connect(('www.TianTianbaby.com',9999))
while True:
mes = input(">> :").strip()
if len(mes) == 0:
continue
if mes == 'q':
break
#客户端发送数据
client.send(mes.encode())
#客户端接收服务端返回的数据
data = client.recv(1024)
#打印返回信息
print("recv:",data.decode())
client.close()
- 服务端
1.导入socket
模块
import socket,os
2.创建实体类接收数据
server = socket.socket()
#绑定要监听的端口
server.bind(('www.TianTianbaby.com',9999))
#监听,参数为最大监听数量
server.listen(5)
print("等待ing")
while True:
#conn就是客户端连过来而在服务器端为其生成的一个连接实例
conn, addr = server.accept()
while True:
#接收数据,参数最大为 1024*8
data = conn.recv(1024)
print("Severrecv:",data)
#客户端断开
if not data:
print("client has lost")
break
#把执行的数据返回给客户端
res = os.popen(data).read()
conn.send(res)
server.close()
三:Socket粘包
- 产生原因:
1.发送端需要等本机的缓冲区满了以后才发送出去,造成粘包(发送数据时间间隔很端,数据很小,会合在一个起,产生粘包)
2.接收端不及时接收缓冲区的包,造成多个包接受(客户端发送一段数据,服务端只收了一小部分,服务端下次再收的时候还是从缓冲区拿上次遗留的数据 ,就产生粘包)
- 解决办法: 介绍两个比较简单的方法
1.sleep 让上一次缓冲区超时.不等下一条.(不建议用)
缺点:造成速度延迟
conn.send(str(len(cmd_res.encode())).encode())
time.sleep(0.5)
conn.send(cmd_res.encode())
2.插入交互 : 插入一个接受响应,如果不响应,第一个发送就不会等待.解决了粘包问题
conn.send(str(len(cmd_res.encode())).encode())
client_ack = conn.rec(1024)#等待确认
conn.send(cmd_res.encode())
另一端手动加一个响应:
伪代码:上一次接收 client.recv(1024)
# client.send("准备好接收了,可以发了".encode())
四:SocketServer服务端
SocketServer
简化了网络服务器的编写。在进行socket
创建时,使用SocketServer会大大减少创建的步骤.
使用方法:
-
创建服务器的步骤。首先,你必须创建一个请求处理类,它是BaseRequestHandler的子类并重载其handle()方法。
-
实例化一个服务器类,传入服务器的地址和请求处理程序类。
-
调用handle_request()(一般是调用其他事件循环或者使用select())或serve_forever()。
继承关系:
+------------+
| BaseServer |
+------------+
|
v
+-----------+ +------------------+
| TCPServer |------->| UnixStreamServer |
+-----------+ +------------------+
|
v
+-----------+ +--------------------+
| UDPServer |------->| UnixDatagramServer |
+-----------+ +--------------------+
代码步骤:
1导入模块SocketServer
import socketserver
2.创建类
class MyTCPHandler(socketserver.BaseRequestHandler):
#与客户端所有的交互在handle完成
def handle(self):
while True:
try:
#接收客户端数据
self.data = self.request.recv(1024).strip()
print("ip",self.client_address[0])
print(self.data)
# 如果客户端断开
if not self.data:
print(self.client_address, "断开了")
break
#给客户端发送数据
self.request.sendall(self.data.upper())
#如果客户端断开了
except ConnectionResetError as e:
print("err",e)
break
3.创建实例
if __name__ == "__main__":
HOST,PORT = 'www.TianTianbaby.com',9999
server =
#创建一个多并发的服务
socketserver.ThreadingTCPServer((HOST,PORT),MyTCPHandler)
#永久打开
server.serve_forever()
五:总结
数据链路层上识别mac
(物理)地址,在网络层识别ip
地址,而在传输层基于一些基本的协议如TCP/IP
,'UDP'建立连接发送消息.
TCP/IP
要建立三次握手,四次接受,上学时候学习网络时候都有学习.
既然是建立的连接,就要发送和接受消息,所以侧重点就是发和收,每个协议都要自己去实现发和收.比较繁琐麻烦.
简单来说socket
就是简化那么复杂的东西,封装给我们一个可以建立连接的模块方便我们使用.
在使用socket
的时候 我们只关心如何收和发就好了,编写出更高效的程序
附:在评论处留下邮箱地址
即可获得全注释源码