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
原创粉丝点击