python学习:编写TCP服务器&UDP服务器
来源:互联网 发布:模拟化学实验软件 编辑:程序博客网 时间:2024/06/05 03:21
python学习:编写TCP服务器&UDP服务器
本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明.
环境:
主机:WIN10
python版本:3.4
开发环境:pyCharm 5.0.2
说明:
项目需求,编写了TCP服务器和UDP服务器负责接收和转发数据。
源代码:
# 导入socket库:import socketimport threading# import timeimport crc16# 服务器配置HOST = '0.0.0.0'# 信令端口PORT_CMD = 12800# 语音端口PORT_AUDIO = 12801# 帧头长度LEN_FRAME_HEAD = 16# 接收超时时间,单位sTIME_OUT_RECV = 60# 接收最大帧长,单位字节MAX_LEN_FRAME = 8192# 最大连接数MAX_CONNECT = 1024# 设备类型DEVICE_SERVER = 0x10DEVICE_STUDENT = 0x11DEVICE_TEACHER = 0x12# 在线列表List_Online_Cmd = []List_Online_Audio = []# crc工具crc_tool = crc16.crc16()def deal_cmd(sock, addr): ''' 信令处理 :param sock:客户端端口 :param addr:客户端地址 :return:无 ''' # 断开连接标志 flag_break = False print('客户端连接,地址:%s:%s...' % addr) # sock.send(b'Welcome!') while True: try: # 接收数据 msg = sock.recv(MAX_LEN_FRAME) # 判断是否断开连接等错误 if not msg: print('错误:空数据包,可能断开连接') flag_break = True break # 判断帧长是否大于帧头长度 if len(msg) < LEN_FRAME_HEAD: print('错误:帧长为%d小于帧头长度%d' % (len(msg), LEN_FRAME_HEAD)) continue # 判断开始标志是否正确 if msg[0] != 0xc5 or msg[1] != 0x5c: print('错误:开始标志错误') continue # 判断帧长是否正确 len_data = (msg[12] << 8) + msg[13] if len(msg) != len_data + LEN_FRAME_HEAD: print('错误:帧长错误,实际帧长%d,理论帧长%d' % (len(msg), len_data + LEN_FRAME_HEAD)) continue # 判断CRC校验是否正确 crc_get = (msg[14] << 8) + msg[15] crc_calc = crc_tool.createcrc(list(msg)[LEN_FRAME_HEAD:]) if crc_get != crc_calc: print('错误:CRC校验错误,实际0x%x,计算0x%x' % (crc_get, crc_calc)) continue # 处理数据 # 判断是否是笔迹包 cmd = (msg[4] << 8) + msg[5] if cmd == 27: # 数据转发 msg_tx = bytearray(msg) msg_tx[3] = DEVICE_SERVER msg_tx[5] = 28 for s in List_Online_Cmd: # i.send(('Hello, %s!' % data.decode('utf-8')).encode('utf-8')) if s != sock: s.send(msg_tx) except socket.timeout: print('连接客户端超时') flag_break = True break # 判断是否断开连接 if flag_break: print('断开与客户端连接...') List_Online_Cmd.remove(sock) for s in List_Online_Audio: if sock.getpeername()[0] == s[0]: print('删除语音客户端%s,%s' % s) List_Online_Audio.remove(s) break sock.close()def thread_socket_cmd(): ''' 信令端口监听线程 :return: 无 ''' # 监听信令端口: socket_cmd = socket.socket(socket.AF_INET, socket.SOCK_STREAM) socket_cmd.bind((HOST, PORT_CMD)) socket_cmd.listen(MAX_CONNECT) print('信令端口%d:开始监听...' % PORT_CMD) while True: # 接受一个新连接: sock_cmd, addr_cmd = socket_cmd.accept() sock_cmd.settimeout(TIME_OUT_RECV) List_Online_Cmd.append(sock_cmd) # print(sock_cmd) # print(sock_cmd.getpeername()[1]) # 创建新线程来处理TCP连接: t = threading.Thread(target=deal_cmd, args=(sock_cmd, addr_cmd)) t.start()def thread_socket_audio(): ''' 语音端口监听线程 :return: 无 ''' # 监听语音端口 socket_audio = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) socket_audio.bind((HOST, PORT_AUDIO)) print('语音端口%d:开始监听...' % PORT_AUDIO) # while True: # # 接收数据: # data, addr = socket_audio.recvfrom(MAX_LEN_FRAME) # # for s in List_Online_Cmd: # # if s.getpeername()[0] == # List_Online_Cmd.append(addr) # # socket_audio.sendto(b'Hello' + data, addr) # 断开连接标志 flag_break = False while True: # 接收数据: msg, addr = socket_audio.recvfrom(MAX_LEN_FRAME) # 判断信令在线列表中是否存在 flag_exist = False for s in List_Online_Cmd: # print(s.getpeername()[0], addr[0]) if s.getpeername()[0] == addr[0]: flag_exist = True break if not flag_exist: print('错误:IP不在信令列表中') continue if List_Online_Audio.count(addr) == 0: List_Online_Audio.append(addr) print('添加语音客户端%s,%s' % addr) # 判断帧长是否大于帧头长度 if len(msg) < LEN_FRAME_HEAD: print('错误:帧长为%d小于帧头长度%d' % (len(msg), LEN_FRAME_HEAD)) continue # 判断开始标志是否正确 if msg[0] != 0xc5 or msg[1] != 0x5c: print('错误:开始标志错误') continue # 判断帧长是否正确 len_data = (msg[12] << 8) + msg[13] if len(msg) != len_data + LEN_FRAME_HEAD: print('错误:帧长错误,实际帧长%d,理论帧长%d' % (len(msg), len_data + LEN_FRAME_HEAD)) continue # 判断CRC校验是否正确 crc_get = (msg[14] << 8) + msg[15] crc_calc = crc_tool.createcrc(list(msg)[LEN_FRAME_HEAD:]) if crc_get != crc_calc: print('错误:CRC校验错误,实际0x%x,计算0x%x' % (crc_get, crc_calc)) # continue # 处理数据 # 判断是否是语音包 cmd = (msg[4] << 8) + msg[5] if cmd == 10000: # 数据转发 msg_tx = bytearray(msg) msg_tx[3] = DEVICE_SERVER msg_tx[4] = (10002 >> 8) & 0xff msg_tx[5] = 10002 & 0xff for s in List_Online_Audio: if s != addr: socket_audio.sendto(msg_tx, s)if __name__ == '__main__': print('服务器开始工作...') # 信令线程 thread_cmd = threading.Thread(target=thread_socket_cmd) thread_cmd.start() # 语音线程 thread_audio = threading.Thread(target=thread_socket_audio) thread_audio.start() # 等待线程结束 thread_cmd.join() thread_audio.join()
0 0
- python学习:编写TCP服务器&UDP服务器
- 服务器的编写(UDP和TCP服务器共存)
- UNIX再学习 -- TCP/UDP 客户机/服务器
- PYTHON中TCP服务器代码的编写。
- .Net 异步Socket编写的UDP和TCP服务器一
- linux下编写tcp服务器学习笔记
- python socket实现简单的(TCP/UDP)服务器/客户端
- Python--UDP时间服务器
- 64-TCP/UDP 混合服务器
- 测试服务器UDP/TCP丢包率
- 并发TCP服务器和并发UDP服务器
- TCP循环服务器 UDP循环服务器 TCP并发服务器
- python实现tcp服务器
- Python--TCP时间服务器
- Python TCP服务器
- python编写的tcp,udp实例
- Linux下TCP/UDP socket服务器模型
- select写的UDP/TCP测试服务器
- CSS的三种使用方法。 行内样式: 内嵌式: 外部式:
- 搞git搞到最后
- ubuntu16.04安装vm-tools
- javascript:; 和 javascript:void(0); 的区别是什么?
- Windows驱动开发之第一个驱动程序
- python学习:编写TCP服务器&UDP服务器
- 编写灵活代码之五大技巧
- Redis学习二
- chrome input 自动填充
- php定时自动执行需要触发一次(后台执行)
- snapd 进入Arch Linux社区软件库(community Repo)
- Android菜鸟学步之Context
- @Resource 与 @Service注解
- swiper的基础使用(十五)