总共两个组程序,
第一组为tcp服务端连接一个客户端
第二组为tcp服务端可连接多个客户端(通过线程进行了class分装)
python2,python3 均运行可用,具体解释见参考
避免粘包的核心代码,以下可运行例子,即将len_data 先通过一条tcp信号先发送过来,设置
# while (len(buf) < len_data and recv_num < self.repeat_num):
# buftmp = client.recv(len_data - len(buf))
# buf = buf + buftmp
# recv_num = recv_num + 1
#
# if len(buf) != len_data:
# print("客户端应发送长度为" + str(len_data) + ", 实际接收长度为: " + str(len(buf)))
# print(buf)
# # time.sleep(100)
# print("跳过129")
# else:
#
# if str(buf) != "b''":
# if python_version == "2":
# original_return_data = buf.encode('hex')
# elif python_version == "3":
# original_return_data = buf.hex()
#
# print("4444444444444444")
# print(len(buf))
#
# print(str(client_addr) +"的地址原数据:"+ str(buf) +" ,转换成十六进制: " + str(original_return_data))
# ana2.distance_analysis(original_return_data)
# else:
# pass
一.只分装了服务端,但是只能连接接收一个客户端
server端
#!/usr/bin/env python2.7
#coding:utf-8
# -*- coding: utf-8 -*-
from socket import *
import json
import struct
import time
import threading
class Server_link():
"""用于初始化。tcp服务端"""
def __init__(self,HOST = '127.0.0.1',PORT = 8081,listen_num = 3):
self.HOST = HOST
self.PORT = PORT
self.listen_num = listen_num
self.repeat_num = 10 #设置当没有接收到完整数据帧的时候,重复连接的次数
self.try_num = 10 # 当客户端掉线后,尝试从连的次数,超过该次数没有连接成功,则认为客户端断线
def start_server(self):
"""开启服务端"""
self.server = socket(AF_INET, SOCK_STREAM)
self.server.bind((self.HOST, self.PORT))
self.server.listen(self.listen_num)
t_server = threading.Thread(target=self.run)
t_server.start()
def run(self):
"""服务端监听程序"""
while True:
try_num = 0
print('等待客户端连接......') # 等待cilent的连接
self.client, client_addr = self.server.accept()
print("成功连接IP:" + str(client_addr) + "的客户端") # (连接对象,客户端的ip和端口)
print("\n")
while True:
try:
length = self.client.recv(4)
len_data = struct.unpack('i', length)
len_data = len_data[0]
print('接收到的原始长度字符%s:' % length)
print('数据长度为%s:' % len_data)
buf = self.receive_real(len_data)
print("接收到的真实数据为: " + str(buf))
json_buf = json.loads(buf)
print(type(json_buf))
status = json_buf['status']
# self.logic_send(status)
except:
if try_num > self.try_num:
print(str(client_addr) + "的客户端连接中断!!!!")
break
else:
try_num = try_num + 1
def receive_real(self,len_data):
"""接收真实数据"""
""" len_data 为预先发过来的真实数据长度 """
buf = b''
recv_size = 0
recv_num = 0 # 接收次数
buf = self.client.recv(len_data)
while (len(buf) <len_data and recv_num < self.repeat_num ):
buftmp = self.client.recv(len_data - len(buf))
buf = buf + buftmp
recv_num = recv_num + 1
if len(buf) != len_data:
print("客户端应发送长度为" + str(len_data) +", 实际接收长度为: " + str(len(buf)) )
time.sleep(100)
return buf
if __name__ == '__main__':
s = Server_link()
s.start_server()
print("开启tcp服务端线程拉起完成")
client 端
#!/usr/bin/env python2.7
#coding:utf-8
# -*- coding: utf-8 -*-
from socket import *
import json
import struct
import time
client = socket(AF_INET, SOCK_STREAM)
client.connect(('127.0.0.1', 8081))
while True:
#打开发1
data={"status":"Link_m","dict": None}
data=json.dumps(data)
# data = "Head" + data
length = len(data)
len_data = struct.pack('i', length)
#固定字节长度,告知数据长度为多少
client.send(len_data)
client.send(data.encode('utf-8'))
server端输出:
接收到的真实数据为: {"status": "Link_m", "dict": null}
<type 'dict'>
接收到的原始长度字符" :
数据长度为34:
接收到的真实数据为: {"status": "Link_m", "dict": null}
<type 'dict'>
接收到的原始长度字符" :
数据长度为34:
接收到的真实数据为: {"status": "Link_m", "dict": null}
<type 'dict'>
接收到的原始长度字符" :
数据长度为34:
接收到的真实数据为: {"status": "Link_m", "dict": null}
二.对服务端和客户端都加上了接收和发送的分装线程类的,一个服务端可以对应多个客户端
server端
#!/usr/bin/env python2.7
#coding:utf-8
# -*- coding: utf-8 -*-
from socket import *
import json
import struct
import time
import threading
class Server_link():
"""用于初始化。tcp服务端"""
def __init__(self,HOST = '127.0.0.1',PORT = 8081,listen_num = 3):
self.HOST = HOST
self.PORT = PORT
self.listen_num = listen_num
self.repeat_num = 10 #设置当没有接收到完整数据帧的时候,重复连接的次数
self.try_num = 10 # 当客户端掉线后,尝试从连的次数,超过该次数没有连接成功,则认为客户端断线
self.client_addr_list = [] # 用于存储连接上的客户端的地址 # client_addr 来自 new_client_socket, client_addr = socket_tcp_server.accept()
def start_server(self):
"""开启服务端"""
self.server = socket(AF_INET, SOCK_STREAM)
self.server.bind((self.HOST, self.PORT))
self.server.listen(self.listen_num)
t_server = threading.Thread(target=self.listen_client)
t_server.start()
def listen_client(self):
"""客户端监听程序,用于监听客户端的连接"""
while True:
print('等待客户端连接......') # 等待cilent的连接
self.hint_client_infor()
client, client_addr = self.server.accept()
self.link_client(client, client_addr) #成功获得客户端,开启针对于该客户端对应的接收与发送函数
def hint_client_infor(self,symbol = ""):
print("当前客户端连接数量: " + str(len(self.client_addr_list)))
for i in self.client_addr_list:
print(symbol + str(i))
print("*" * 100)
print("\n")
def link_client(self,client,client_addr):
self.client_addr_list.append((client,client_addr))
# t_client_recv = threading.Thread(target=self.client_recv, args=((client,client_addr),))
# t_client_recv.start()
t_client_send = threading.Thread(target=self.client_send, args=((client,client_addr),))
t_client_send.start()
print("成功连接IP:" + str(client_addr) + "的客户端") # (连接对象,客户端的ip和端口)
print("\n")
def client_recv(self,data):
client = data[0]
client_addr = data[1]
try_num = 0
while True:
try:
length = client.recv(4)
len_data = struct.unpack('i', length)
len_data = len_data[0]
print('接收到的原始长度字符%s:' % length)
print('数据长度为%s:' % len_data)
buf = self.receive_real(client,len_data)
print("接收到的真实数据为: " + str(buf))
json_buf = json.loads(buf)
print(type(json_buf))
status = json_buf['status']
except:
if try_num > self.try_num:
print(str(client_addr) + "的客户端连接中断!!!!")
if data in self.client_addr_list:
self.client_addr_list.remove(data)
client.close()
self.hint_client_infor(symbol="recv: ")
break
else:
try_num = try_num + 1
def client_send(self,data):
client = data[0]
client_addr = data[1]
try_num = 0
json_data = {"status": "from_server", "dict": None}
while True:
try:
self.send_data(client,json_data)
except:
if try_num > self.try_num:
print(str(client_addr) + "的客户端连接中断!!!!")
if data in self.client_addr_list:
self.client_addr_list.remove(data)
client.close()
self.hint_client_infor(symbol="send: ")
break
else:
try_num = try_num + 1
def receive_real(self,client,len_data):
"""接收真实数据"""
""" len_data 为预先发过来的真实数据长度 """
buf = b''
recv_size = 0
recv_num = 0 # 接收次数
buf = client.recv(len_data)
while (len(buf) <len_data and recv_num < self.repeat_num ):
buftmp = client.recv(len_data - len(buf))
buf = buf + buftmp
recv_num = recv_num + 1
if len(buf) != len_data:
print("客户端应发送长度为" + str(len_data) +", 实际接收长度为: " + str(len(buf)) )
time.sleep(100)
return buf
def send_data(self,client,json_data):
"""用于发送数据"""
json_data = json.dumps(json_data)
# data = "Head" + data
length = len(json_data)
len_data = struct.pack('i', length)
# 固定字节长度,告知数据长度为多少
client.send(len_data)
client.send(json_data.encode('utf-8'))
if __name__ == '__main__':
s = Server_link()
s.start_server()
print("开启tcp服务端线程拉起完成")
client端
#!/usr/bin/env python2.7
#coding:utf-8
# -*- coding: utf-8 -*-
from socket import *
import json
import struct
import time
import threading
class Client_link():
"""用于初始化。tcp客户端"""
def __init__(self,HOST = '127.0.0.1',PORT = 8081):
self.HOST = HOST
self.PORT = PORT
self.repeat_num = 10 #设置当没有接收到完整数据帧的时候,重复连接的次数
def start_client(self):
"""开启客户端"""
self.client = socket(AF_INET, SOCK_STREAM)
self.client.connect((self.HOST, self.PORT))
t_client = threading.Thread(target=self.run)
t_client.start()
def run(self):
"""客户端监听程序"""
while True:
print('开始连接下位机服务端......') # 等待cilent的连接
while True:
length = self.client.recv(4)
len_data = struct.unpack('i', length)
len_data = len_data[0]
print('接收到的原始长度字符%s:' % length)
print('数据长度为%s:' % len_data)
buf = self.receive_real(len_data)
print("接收到的真实数据为: " + str(buf))
json_buf = json.loads(buf)
print(type(json_buf))
status = json_buf['status']
#self.logic_send(status)
def receive_real(self,len_data):
"""接收真实数据"""
""" len_data 为预先发过来的真实数据长度 """
buf = b''
recv_size = 0
recv_num = 0 # 接收次数
buf = self.client.recv(len_data)
while (len(buf) <len_data and recv_num < self.repeat_num ):
buftmp = self.client.recv(len_data - len(buf))
buf = buf + buftmp
recv_num = recv_num + 1
if len(buf) != len_data:
print("服务端应发送长度为" + str(len_data) +", 实际接收长度为: " + str(len(buf)) )
time.sleep(100)
return buf
def send_data(self,data):
"""用于发送数据"""
data = json.dumps(data)
# data = "Head" + data
length = len(data)
len_data = struct.pack('i', length)
# 固定字节长度,告知数据长度为多少
self.client.send(len_data)
self.client.send(data.encode('utf-8'))
if __name__ == '__main__':
c = Client_link()
c.start_client()
print("开启tcp客户端线程拉起完成")
# data = {"status": "cscs", "dict": None}
# while True:
# c.send_data(data)
# time.sleep(0.5)
服务端连接输出
等待客户端连接......开启tcp服务端线程拉起完成
当前客户端连接数量: 0
****************************************************************************************************
成功连接IP:('127.0.0.1', 55969)的客户端
等待客户端连接......
当前客户端连接数量: 1
(<socket.socket fd=716, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8081), raddr=('127.0.0.1', 55969)>, ('127.0.0.1', 55969))
****************************************************************************************************
('127.0.0.1', 55969)的客户端连接中断!!!!
当前客户端连接数量: 0
****************************************************************************************************
成功连接IP:('127.0.0.1', 55971)的客户端
等待客户端连接......
当前客户端连接数量: 1
(<socket.socket fd=724, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8081), raddr=('127.0.0.1', 55971)>, ('127.0.0.1', 55971))
****************************************************************************************************
成功连接IP:('127.0.0.1', 55972)的客户端
等待客户端连接......
当前客户端连接数量: 2
(<socket.socket fd=724, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8081), raddr=('127.0.0.1', 55971)>, ('127.0.0.1', 55971))
(<socket.socket fd=808, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8081), raddr=('127.0.0.1', 55972)>, ('127.0.0.1', 55972))
****************************************************************************************************
客户端连接输出
数据长度为39:
接收到的真实数据为: {"status": "from_server", "dict": null}
<type 'dict'>
接收到的原始长度字符' :
数据长度为39:
接收到的真实数据为: {"status": "from_server", "dict": null}
<type 'dict'>
接收到的原始长度字符' :
数据长度为39:
接收到的真实数据为: {"status": "from_server", "dict": null}
<type 'dict'>
接收到的原始长度字符' :
数据长度为39:
接收到的真实数据为: {"status": "from_server", "dict": null}
<type 'dict'>
接收到的原始长度字符' :
数据长度为39: