python基础2-socket编程
服务端 server = socket.socket(family=AF_INET,type=SOCK_STREAM,proto=0,fileno=None) 地址簇, tcp/ip server.bind(localhost,9999) 绑定端口 server.listen() 监听 while True: conn,addr = server.accept() #阻塞 while True: print("new conn",addr) data = conn.recv(1024) #conn是开启的连接的实例,官方建议不超过8192,#recv默认是阻塞的 if not data: break #客户端已断开,conn.recv收到的就都是空数据 print(data) conn.send(data.upper()) 详解: family address AF_INET ipv4 AF_INET6 ipv6 AF_UNIX local socket protocol type sock.SOCK_STREAM tcp/ip sock.SOCK_DGRAM udp 客户端 client = socket.socket() client.connect(server.ip,server.port) client.send(data) client.recv(1024)
简单实例:
1.socket_client.py
#客户端
import socket
client = socket.socket() #声明socket类型,同时生成socket连接对象
client.connect(("localhost",6969))
client.send(b"hello,world")
data = client.recv(1024)
print("recv:",data)
client.close()
返回:
recv: b'HELLO,WORLD'
2.socket_server.py
#服务端
import socket
server = socket.socket()
server.bind(("localhost",6969)) #绑定要监听的端口
server.listen() #监听
print("我要开始等待电话")
conn,addr = server.accept() #等电话打进来
#conn就是客户端连过来而在服务器端为其生成的一个连接实例
#accept会返回俩个值,一个flag,一个地址
print(conn,addr)
print("电话来啦")
data = conn.recv(1024)
print("recv:",data)
conn.send(data.upper())
# server.close()
返回:
我要开始等待电话
<socket.socket fd=272, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 6969), raddr=('127.0.0.1', 52351)> ('127.0.0.1', 52351)
电话来啦
recv: b'hello,world'
3.socket——ssh远程命令返回结果实例
socket_ssh_server.py
import socket,os
server = socket.socket()
server.bind(('localhost',9999))
server.listen()
while True:
conn,addr = server.accept()
print("new conn:",addr)
while True:
print("等待新指令")
data = conn.recv(1024)
if not data:
print("客户端已断开")
break
print("执行指令:",data)
cmd_res = os.popen(data.decode()).read() #接收字符串,执行结果也是字符串
print("before send",len(cmd_res))
if len(cmd_res) == 0:
cmd_res = "cmd has no output..."
conn.send( str(len(cmd_res.encode())).encode("utf-8") ) #先发大小给客户端
conn.send(cmd_res.encode("utf-8"))
print("send done")
server.close()
socket_ssh_client.py
import socket
client = socket.socket()
client.connect(('localhost',9999))
while True:
cmd = input(">>:").strip()
if len(cmd) == 0:continue
client.send(cmd.encode("utf-8"))
cmd_res_size = client.recv(1024) #接收命令结果的长度
print("命令结果大小:",cmd_res_size)
received_size = 0
received_data = b''
while received_size != int(cmd_res_size.decode()):
data = client.recv(1024)
received_size += len(data) #每次收到的有可能小于1024,所以必须用len判断
# print(data.decode())
received_data += data
print(received_size)
else:
print("cmd res received done...",received_size)
print(received_data.decode())
# cmd_res = client.recv(1024)
# print(cmd_res.decode())
client.close()
4.解决socket粘包
import socket,os,time server = socket.socket() server.bind(('localhost',9999)) server.listen() while True: conn,addr = server.accept() print("new conn:",addr) while True: print("等待新指令") data = conn.recv(1024) if not data: print("客户端已断开") break print("执行指令:",data) cmd_res = os.popen(data.decode()).read() #接收字符串,执行结果也是字符串 print("before send",len(cmd_res)) if len(cmd_res) == 0: cmd_res = "cmd has no output..." conn.send( str(len(cmd_res.encode())).encode("utf-8") ) #先发大小给客户端 # time.sleep(0.5) client_ack = conn.recv(1024) #wait client to confirm 在俩个send之间插入一个交互 print("ack from client:",client_ack) conn.send(cmd_res.encode("utf-8")) print("send done") server.close()
import socket client = socket.socket() client.connect(('localhost',9999)) while True: cmd = input(">>:").strip() if len(cmd) == 0:continue client.send(cmd.encode("utf-8")) cmd_res_size = client.recv(1024) #接收命令结果的长度 print("命令结果大小:",cmd_res_size) client.send("准备好接收了,我,可以发啦".encode("utf-8")) received_size = 0 received_data = b'' while received_size != int(cmd_res_size.decode()): data = client.recv(1024) received_size += len(data) #每次收到的有可能小于1024,所以必须用len判断 # print(data.decode()) received_data += data print(received_size) else: print("cmd res received done...",received_size) print(received_data.decode()) # cmd_res = client.recv(1024) # print(cmd_res.decode()) client.close()
注:在linux上执行df命令就很明显的粘包,win端不易发现
5.socket实现文件发送,仅实现get,并且是在linux之间实现
import socket,os,time,hashlib server = socket.socket() server.bind(('localhost',9999)) server.listen() while True: conn,addr = server.accept() print("new conn:",addr) while True: print("等待新指令") data = conn.recv(1024) if not data: print("客户端已断开") break cmd,filename = data.decode().split() print(filename) if os.path.isfile(filename): f = open(filename,'rb') m = hashlib.md5() file_size = os.stat(filename).st_size conn.send(str(file_size).encode() ) #send file size conn.recv(1024) #wait for ack for line in f: #f是迭代器的形式 m.update(line) conn.send(line) print("file md5",m.hexdigest()) f.close() conn.send(m.hexdigest().encode()) #send md5 print("send done") server.close()
import socket,hashlib client = socket.socket() client.connect(('localhost',9999)) while True: cmd = input(">>:").strip() if len(cmd) == 0:continue if cmd.startwith("get"): client.send(cmd.encode()) server_response = client.recv(1024) print("server response",server_response) client.send(b"ready to recv file") file_total_size = int(server_response.decode()) received_size = 0 filename = cmd.split()[1] f = open(filename + '.new','wb') m = hashlib.md5() while received_size < file_total_size: surplus = file_total_size - received_size #剩余要收的大小 if surplus >1024: #要收不止一次 size = 1024 else: #最后一次剩余多少收多少 #防止与最后的md5值进行粘包 size = surplus print("last receive:",size) data = client.recv(size) received_size += len(data) m.update(data) f.write(data) # print(file_total_size,received_size) #每次循环都打印,有点刷屏,显得慢 else: new_file_md5 = m.hexdigest() print("file recv done",received_size,file_total_size) f.close() server_file_md5 = client.recv(1024) print("server file md5:",server_file_md5) print("client file md5:",new_file_md5) client.close()
注:其中有md5校验,故较慢

浙公网安备 33010602011771号