网络编程(二)
一.socket(套接字)
1.基于TCP协议的socket通信
sever端
1 import socket 2 sk = socket.socket() 3 sk.bind(('127.0.0.1',8898)) #把地址绑定到套接字 4 sk.listen() #监听链接 5 conn,addr = sk.accept() #接受客户端链接 6 ret = conn.recv(1024) #接收客户端信息 7 print(ret) #打印客户端信息 8 conn.send(b'hi') #向客户端发送信息 9 conn.close() #关闭客户端套接字 10 sk.close() #关闭服务器套接字(可选)
client端
import socket sk = socket.socket() # 创建客户套接字 sk.connect(('127.0.0.1',8898)) # 尝试连接服务器 sk.send(b'hello!') ret = sk.recv(1024) # 对话(发送/接收) print(ret) sk.close() # 关闭客户套接字
2.标准通信循环
server端
import socket server = socket.socket() # 生成一个对象 server.bind(('127.0.0.1',8080)) # 绑定ip和port server.listen() # 半连接池 while True: conn, addr = server.accept() print(addr) # ('127.0.0.1', 51323) 客户端的地址 while True: try: data = conn.recv(1024) print(data) if len(data) == 0:break conn.send(data.upper()) except ConnectionResetError as e: print(e) break conn.close()
client端
import socket client = socket.socket() client.connect(('127.0.0.1',8080)) while True: msg = input('>>>:').encode('utf-8') if len(msg) == 0:continue client.send(msg) data = client.recv(1024) print(data)
3.粘包问题
server端
import socket import subprocess sk = socket.socket() sk.bind(('127.0.0.1',8080)) sk.listen() while True: conn,addr = sk.accept() while True: try: cmd = conn.recv(1024).decode('utf-8') if len(cmd) == 0:break res = subprocess.Popen(cmd,shell= True, stderr=subprocess.PIPE, stdout=subprocess.PIPE) stdout = res.stdout.read() stderr = res.stderr.read() conn.send(stdout) conn.send(stderr) except ConnectionResetError: break
client端
import socket sk = socket.socket() sk.connect(('127.0.0.1',8080)) while True: cmd = input('请输入cmd:').strip() if len(cmd) == 0 :continue sk.send(cmd.encode('utf-8')) res = sk.recv(1024) print(res.decode('gbk'))
粘包造成的原因:
粘包现象只发生在tcp协议中:
1.从表面看,粘包问题主要是因为发送方和接收方的缓存机制,tcp协议面向流通信的特点
2.实际上,主要还是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的
4.解决粘包
server端
import socket import subprocess import json import struct sk = socket.socket() sk.bind(('127.0.0.1',8080)) sk.listen() while True: conn,addr = sk.accept() while True: try: cmd = conn.recv(1024).decode('utf-8') if len(cmd) == 0:break res = subprocess.Popen(cmd,shell= True, stderr=subprocess.PIPE, stdout=subprocess.PIPE) stdout = res.stdout.read() stderr = res.stderr.read() ret = stdout+stderr head = {'name':'zzp','size':len(ret)} json_head = json.dumps(head) head_pack = struct.pack('i',len(json_head)) sk.send(head_pack) sk.send(json_head.encode('utf-8')) sk.send(ret) except ConnectionResetError: break
client端
import socket import struct import json sk = socket.socket() sk.connect(('127.0.0.1',8080)) while True: cmd = input('请输入cmd:').strip() if len(cmd) == 0 :continue sk.send(cmd.encode('utf-8')) head_pack = sk.recv(4) head_len = struct.unpack('i',head_pack)[0] head_json = sk.recv(head_len).decode('utf-8') head = json.loads(head_json) size = head['size'] recv_size = 0 real_data = b'' while recv_size < size: data = sk.recv(1024) real_data += data recv_size += len(data) print(real_data.decode('gbk'))
万般皆下品,唯有读书高!