Python之socket
Socket通长也称作"套接字",用于描述IP地址和端口,是一个通信的句柄.
vim day8-16.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | #!/usr/bin/env python #coding:utf-8 import socket def handle_request(client): buf = client.recv( 1024 ) print buf client.send( "HTTP/1.1 200 OK\r\n\r\n" ) client.send( "Hello, World" ) def main(): #创建socket对象 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #bind方法监听某个端口 sock.bind(( '127.0.0.1' , 8080 )) #开始监听, sock.listen( 5 ) while True : #阻塞,等... #直到有请求连接 connection, address = sock.accept() #connection代表客户端sockert对象 #address客户端IP地址 handle_request(connection) connection.close() if __name__ = = '__main__' : main() |
运行,然后在开启一个客户端访问
本客户端返回
使用python建立一个socket的服务端和客户端
vim socket_server.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #!/usr/bin/env python #coding:utf-8 import socket obj_server = socket.socket() obj_server.bind(( 'localhost' , 8341 )) obj_server.listen( 5 ) #开始监听最大连接数5 while True : print 'waiting...' conn,addr = obj_server.accept() client_data = conn.recv( 1024 ) #最多一次性接收1024size print client_data conn.send( '好的' ) conn.close() |
vim socket_client.py
1 2 3 4 5 6 7 8 9 10 11 12 13 | #!/usr/bin/env python #coding:utf-8 import socket obj = socket.socket() obj.connect(( 'localhost' , 8341 )) obj.send( '我爱北京天安门' ) server_data = obj.recv( 1024 ) print server_data obj.close() ~ |
运行服务端,然后新开一个窗口运行客户端
智能机器人实例
vim day8-18.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | #!/usr/bin/env python # -*- coding:utf-8 -*- import socket ip_port = ( '127.0.0.1' , 8888 ) sk = socket.socket() sk.bind(ip_port) sk.listen( 5 ) while True : conn,address = sk.accept() conn.sendall( '欢迎致电10086,请输入1xxx,0转人工服务' ) Flag = True while Flag: data = conn.recv( 1024 ) #阻塞等待客户端发生数据 print data #打印从客户端接收到的数据 if data = = 'exit' : Flag = False elif data = = '0' : conn.sendall( '您的通话可能被录音' ) else : conn.sendall( '请重新输入' ) conn.close() |
vim day8-19.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #!/usr/bin/env python # -*- coding:utf-8 -*- import socket ip_port = ( '127.0.0.1' , 8888 ) sk = socket.socket() sk.connect(ip_port) #客户端连接服务端 sk.settimeout( 5 ) while True : data = sk.recv( 1024 ) #接收服务端数据欢迎致电... print 'recevie:' ,data inp = raw_input ( 'please input:' ) sk.sendall(inp) if inp = = 'exit' : break sk.close() |
执行过程
服务端
客户端
PS:一个socket同时只能处理一个请求,如果一个请求在连接中,其他请求在过来将排队等待,等待时间为设置的超时时间为5s,python提供了一个模块用于多线程模块socketserver
SoketServer
多线程条件
1,必须写一个类
2,必须继承SocketServer.BaseRequestHandler
3,必须写一个方法而且方法名必须为handle
4,必须调用ThreadingTCPServer方法来实现多线程
day8-22.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #!/usr/bin/env python # -*- coding:utf-8 -*- import SocketServer import os class MyServer(SocketServer.BaseRequestHandler): def handle( self ): print "--got connection from" , self .client_address while True : data = self .request.recv( 1024 ) print "Recv from cmd:%s" % (data) cmd_res = os.popen(data).read() print 'cmd_res:' , len (cmd_res) #打印服务器发送数据长度 self .request.sendall(cmd_res) if __name__ = = '__main__' : server = SocketServer.ThreadingTCPServer(( '127.0.0.1' , 8009 ),MyServer) server.serve_forever() #永久运行 |
客户端vim day8-23.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | #!/usr/bin/env python # -*- coding:utf-8 -*- import socket ip_port = ( '127.0.0.1' , 8009 ) sk = socket.socket() sk.connect(ip_port) sk.settimeout( 5 ) while True : # data = sk.recv(1024) # print 'receive:',data inp = raw_input ( 'please input:' ) sk.sendall(inp) while True : data = sk.recv( 1024 ) print "---data---" # if len(data) == 0: if len (data) < 1024 : print '---not data---' break print data if inp = = 'exit' : break sk.close() |
客户端输入命令服务端把命令结果返回给客户端打印
修改代码让服务器在发送数据之前就把要发送的大小发送给客户端,客户端根据包的大小进行判断打印
服务端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #!/usr/bin/env python # -*- coding:utf-8 -*- import SocketServer import os class MyServer(SocketServer.BaseRequestHandler): def handle( self ): print "--got connection from" , self .client_address while True : data = self .request.recv( 1024 ) print "Recv from cmd:%s" % (data) cmd_res = os.popen(data).read() print 'cmd_res:' , len (cmd_res) #打印服务器发送数据长度 self .request.send( str ( len (cmd_res)) ) #服务端要给客户端发多长数据 self .request.sendall(cmd_res) if __name__ = = '__main__' : server = SocketServer.ThreadingTCPServer(( '127.0.0.1' , 8009 ),MyServer) server.serve_forever() #永久运行 |
客户端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | #!/usr/bin/env python # -*- coding:utf-8 -*- import socket ip_port = ( '127.0.0.1' , 8009 ) sk = socket.socket() sk.connect(ip_port) sk.settimeout( 5 ) while True : # data = sk.recv(1024) # print 'receive:',data inp = raw_input ( 'please input:' ) sk.sendall(inp) res_size = sk.recv( 1024 ) print "goint to recv data size:" ,res_size, type (res_size) #打印将收到多少数据和数据类型 total_size = int (res_size) #共要收取的 received_size = 0 while True : data = sk.recv( 1024 ) received_size + = len (data) print "---data---" # if len(data) == 0: # if len(data) < 1024: if total_size = = received_size: #如果收到的大小等于收到的大小代表收完了 print data print '---not data---' break print data if inp = = 'exit' : break sk.close() |
PS:这样也会出现问题,这两个包可能在网络层集合成一个包发送给客户端导致客户端接收ValueError,这种现象叫连包,可以通过修改服务器端代码(比如两个包之间sleep1秒再发送下一个包),但是效率太低
可以通过在两条消息直接加代码解决
服务端
客户端回一条可以是一个空格
作业:客户端往服务端发文件,客户端可以从服务端下载文件,实现文件MD5验证和用户验证
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!