socket基础篇
server_scoket.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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | #!/usr/bin/env python3.5 # -*- coding:utf-8 -*- import socket import subprocess ip_port = ( '0.0.0.0' , 9999 ) sk = socket.socket() sk.bind(ip_port) sk.listen( 2 ) cid = 0 while True : cid + = 1 print ( 'server waiting...' ) try : conn,addr = sk.accept() # client_data = conn.recv(1024) # print(str(client_data,'utf8')) # conn.sendall(bytes('不要回答,不要回答,不要回答','utf8')) while True : try : client_data = conn.recv( 8192 ) str_clinet_data = str (client_data, 'utf8' ).strip() if not client_data.decode(): print ( "\033[1;31;0m客户端未发送数据!\033[0m" ) break print ( "接收数据,客户端%d:\033[1;31;0m%s\033[0m" % (cid,str_clinet_data)) cmd_data = subprocess.Popen(str_clinet_data,shell = True ,stdout = subprocess.PIPE,stderr = subprocess.PIPE) cmd_data_out , cmd_error = cmd_data.communicate() # 返回bytes # if cmd_error != bytes("","utf-8"): if cmd_error: cmd_data_result = cmd_error else : cmd_data_result = cmd_data_out try : print ( str (cmd_data_result, "gbk" )) except UnicodeDecodeError: print ( str (cmd_data_result, "utf-8" )) # conn.send(client_data) cmd_result_size = b "CMD_RESULT_SIZE|%d" % len (cmd_data_result) # print(cmd_result_size) conn.send(cmd_result_size) client_ack = conn.recv( 20 ) if client_ack = = b "CMD_RESULT_SIZE_OK" : print ( "收到客户端的确认,开始发送数据!" ) conn.send(cmd_data_result) except ConnectionResetError as e: print (e) print ( "\033[1;31;0m客户端%d关闭连接!\033[0m" % cid) break except KeyboardInterrupt as e: print (e) break conn.close() |
client.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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | #!/usr/bin/env python # -*- coding:utf-8 -*- import socket ip_port = ( '192.168.5.124' , 9999 ) sk = socket.socket() sk.connect(ip_port) # sk.sendall(bytes('请求占领地球','utf8')) # server_reply = sk.recv(1024) # print(str(server_reply,'utf8')) while True : try : user_input = input ( "cmd>>:" ).strip() except KeyboardInterrupt as e: print (e) break if user_input = = "": continue if user_input = = 'q' : break sk.send(bytes(user_input, 'utf8' )) # print("发送数据: \033[1;32;0m%s\033[0m"%user_input) server_reply_size_data = sk.recv( 50 ) # print(server_reply_size_data) server_reply_size_flag, server_reply_size = server_reply_size_data.decode( "utf-8" ).split( "|" ) server_reply_size = int (server_reply_size) if server_reply_size_flag = = "CMD_RESULT_SIZE" : print ( "服务端将发送字节数:%d" % server_reply_size) print ( "给服务端发送确认!" ) sk.send(b "CMD_RESULT_SIZE_OK" ) server_result = b"" recv_size = 0 # n = 1 while recv_size < server_reply_size: server_reply = sk.recv( 500 ) server_result + = server_reply recv_size + = len (server_reply) print ( "共接收%d字节" % recv_size) # code,server_result = str(server_reply[:9].split(b'0')[0],"utf-8"),server_reply[9:] else : print ( "------load-done-----" ) print ( "\033[1;32;0m%s\033[0m" % str (server_result, "gbk" ),end = "") # try: # print("接收数据: \033[1;32;0m%s\033[0m"%str(server_reply,'utf-8')) # except UnicodeDecodeError: # print("接收数据: \033[1;32;0m%s\033[0m"%str(server_reply,'gbk')) sk.close() |
环境:server运行在linux,client运行在linux和windows:
1、在windowns上用tskill pid时,windowns会发生rst包,且服务端if not data无法抓到,而是在
except ConnectionResetError as e:
print(e)
捕捉到了。

2、windows 上Ctrl + C ,linus上 kill pid、kill -9 pid 、Ctrl + c,客户端会发送fin来进行正常的结束会话
3、阻塞
开启多个客户端会发生阻塞,但是正常的tcp三次握手可以正常连接,只是发生过去的数据服务器会回应空数据的包。
及时我在客户端加了if not data: 也是没用的 ,应为如果recv()收到ack应该是会阻塞的(不确定,可能是这样)。
客户端还是卡住:
,且客户端和服务器端也没有数据传输。
某一个客户端结束会话后,这个客户端会马上收到服务器端的数据。
服务器端的recv()收到ack,recv()会阻塞。
4、客户端连接超过监听设置数。sk.listen(2),表示可以挂起两个。
第一个client在linux,然后再windows开了三个客户端,都可以连上(很奇怪),当在windows开启第四个client时,出现问题,如下:
这里服务器端的那个端口为14378的连接已经断开。14378的客户端再发生数据库如下:
客户端一个一个断开后,挂起的客户端收到服务器的数据,客户端的recv()一个个被"激活"。
但是当server起在windows时,确实只能挂起两个:
为了抓包,第四个客户端在linux发起:
5、当发送数据为空或回车时,send()会阻塞:
红框的包是以前的。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!