首页 > 编程语言 >20240809-python实现TCP通信

20240809-python实现TCP通信

时间:2024-08-09 18:06:18浏览次数:11  
标签:log info socket python send TCP data 20240809 客户端

python实现TCP通讯

1.0 版本(备份)
import socket
from logUtils import log
from api import Api


def handle_client(client_socket, addr):
    log.info(f"客户端的ip地址和端口号: {addr}")
    try:
        while True:
            # 接收客户端发送的数据, 这次接收数据的最大字节数是1024
            recv_data = client_socket.recv(1024)
            if not recv_data:
                # 如果没有接收到数据,说明客户端可能已经关闭了连接
                break
                # 对二进制数据进行解码
            recv_content = recv_data #.decode("utf-8")
            log.info(f'-----------------------------------------begin-------------------------------------')
            log.info(f"接收客户端的数据为: {recv_content}")
            api = Api()
            send_data = api.Message_parsing(recv_data)
            # 准备发送的数据
            if send_data:
                print(f'要发送的数据:{send_data}')
                # send_data = b'h\x19\x00hK\x01\x00T\x07\x00\x02`\x00\x01\x00cE\x86A:3\x12\nXQ\x18\x10q!\x06{\x16'
                # 发送数据给客户端
                client_socket.send(send_data)
                print('发送成功!')
            log.info(f'-----------------------------------------end-------------------------------------')
    except Exception as e:
        print(f"处理客户端时发生错误: {e}")
        log.info(f'-----------------------------------------error-------------------------------------')
    finally:
        # 关闭与客户端的套接字
        client_socket.close()
        print(f"与客户端 {addr} 的连接已关闭")


if __name__ == '__main__':
    # 创建tcp服务端套接字
    tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 设置端口号复用,让程序退出端口号立即释放
    tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
    # 给程序绑定端口号
    tcp_server_socket.bind(("0.0.0.0", 6999))
    # 设置监听
    tcp_server_socket.listen(128)
    log.info("服务器开始监听端口号: 6999")

    try:
        while True:
            # 等待客户端建立连接的请求
            service_client_socket, ip_port = tcp_server_socket.accept()
            log.info(f"客户端的IP地址和端口号: {ip_port}")

            # 在单独的线程或进程中处理客户端连接,这里简化为直接调用处理函数
            handle_client(service_client_socket, ip_port)


    except KeyboardInterrupt:
        print("服务器接收到停止信号,正在关闭...")
    finally:
        # 关闭服务端的套接字(通常在实际应用中,这一步会在所有客户端连接都关闭后执行,但在这里我们直接响应中断信号)
        tcp_server_socket.close()

我想把他修改成可以服务端主动发报文的,进行了这样的操作:

import socket
from logUtils import log
from api import Api


def handle_client(client_socket, addr):
    log.info(f"客户端的ip地址和端口号: {addr}")
    # status = False
    try:
        while True:
            api = Api()
            # if status:
            #     print(f'04:\n20:插座启停')
            #     number = input("请输入你要调用的接口编号:")
            #
            #     avtive_send_data , statu = api.get_active_send_data(str(number))
            #     status = statu
            #     if avtive_send_data:
            #         print(f'要发送的数据:{avtive_send_data}')
            #         # send_data = b'h\x19\x00hK\x01\x00T\x07\x00\x02`\x00\x01\x00cE\x86A:3\x12\nXQ\x18\x10q!\x06{\x16'
            #         # 发送数据给客户端
            #         client_socket.send(avtive_send_data)
            #         print('发送成功!')

            # 接收客户端发送的数据, 这次接收数据的最大字节数是1024
            recv_data = client_socket.recv(1024)
            if not recv_data:
                # 如果没有接收到数据,说明客户端可能已经关闭了连接
                break
                # 对二进制数据进行解码
            recv_content = recv_data #.decode("utf-8")
            log.info(f'-----------------------------------------begin-------------------------------------')
            log.info(f"接收客户端的数据为: {recv_content}")

            send_data = api.Message_parsing(recv_data)
            # 准备发送的数据
            if send_data:
                log.info(f'要发送的数据:{send_data}')
                print(f'要发送的数据:{send_data}')
                # send_data = b'h\x19\x00hK\x01\x00T\x07\x00\x02`\x00\x01\x00cE\x86A:3\x12\nXQ\x18\x10q!\x06{\x16'
                # 发送数据给客户端
                client_socket.send(send_data)
                log.info('发送成功!')
                print('发送成功!')
            log.info(f'-----------------------------------------end-------------------------------------')
    except Exception as e:
        log.info(f"处理客户端时发生错误: {e}")
        print(f"处理客户端时发生错误: {e}")
        log.info(f'-----------------------------------------error-------------------------------------')
    finally:
        # 关闭与客户端的套接字
        client_socket.close()
        print(f"与客户端 {addr} 的连接已关闭")


if __name__ == '__main__':
    # 创建tcp服务端套接字
    tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 设置端口号复用,让程序退出端口号立即释放
    tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
    # 给程序绑定端口号
    tcp_server_socket.bind(("0.0.0.0", 6999))
    # 设置监听
    tcp_server_socket.listen(128)
    log.info("服务器开始监听端口号: 6999")

    try:
        while True:
            # 等待客户端建立连接的请求
            service_client_socket, ip_port = tcp_server_socket.accept()
            log.info(f"客户端的IP地址和端口号: {ip_port}")

            # 在单独的线程或进程中处理客户端连接,这里简化为直接调用处理函数
            handle_client(service_client_socket, ip_port)


    except KeyboardInterrupt:
        print("服务器接收到停止信号,正在关闭...")
    finally:
        # 关闭服务端的套接字(通常在实际应用中,这一步会在所有客户端连接都关闭后执行,但在这里我们直接响应中断信号)
        tcp_server_socket.close()

具体就是增加了一个状态变量,如果心跳了,就把状态设置成true,状态为true时,每次发送、接收报文都先判断一下是否需要主动发送。目前原理上感觉是可行的,我也写了一个测试的服务端-客户端,测试结果:可行。

但是这样子,在api.py里增加返回状态时,出现了报错。

具体是SIM卡上报信息是报错了:

cannot unpack non-iterable NoneType object

这个报错是对一个NoneType进行了数据操作,我找了半天也没找到SIM卡接口里有什么数据操作。

最后恢复一下代码,又能运行了。我再一步一步看看,到底是改了哪里出现了错误。

排查错误:
import socket
from logUtils import log
from api import Api


def handle_client(client_socket, addr):
    log.info(f"客户端的ip地址和端口号: {addr}")
    status = False
    try:
        while True:
            api = Api()
            if status:
                print(f'04:\n20:插座启停')
                number = input("请输入你要调用的接口编号:")

                avtive_send_data , statu = api.get_active_send_data(str(number))
                status = statu
                if avtive_send_data:
                    print(f'要发送的数据:{avtive_send_data}')
                    # send_data = b'h\x19\x00hK\x01\x00T\x07\x00\x02`\x00\x01\x00cE\x86A:3\x12\nXQ\x18\x10q!\x06{\x16'
                    # 发送数据给客户端
                    client_socket.send(avtive_send_data)
                    print('发送成功!')

            # 接收客户端发送的数据, 这次接收数据的最大字节数是1024
            recv_data = client_socket.recv(1024)
            if not recv_data:
                # 如果没有接收到数据,说明客户端可能已经关闭了连接
                break
                # 对二进制数据进行解码
            recv_content = recv_data #.decode("utf-8")
            log.info(f'-----------------------------------------begin-------------------------------------')
            log.info(f"接收客户端的数据为: {recv_content}")

            send_data = api.Message_parsing(recv_data)
            # 准备发送的数据
            if send_data:
                log.info(f'要发送的数据:{send_data}')
                print(f'要发送的数据:{send_data}')
                # send_data = b'h\x19\x00hK\x01\x00T\x07\x00\x02`\x00\x01\x00cE\x86A:3\x12\nXQ\x18\x10q!\x06{\x16'
                # 发送数据给客户端
                client_socket.send(send_data)
                log.info('发送成功!')
                print('发送成功!')
            log.info(f'-----------------------------------------end-------------------------------------')
    except Exception as e:
        log.info(f"处理客户端时发生错误: {e}")
        print(f"处理客户端时发生错误: {e}")
        log.info(f'-----------------------------------------error-------------------------------------')
    finally:
        # 关闭与客户端的套接字
        client_socket.close()
        print(f"与客户端 {addr} 的连接已关闭")


if __name__ == '__main__':
    # 创建tcp服务端套接字
    tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 设置端口号复用,让程序退出端口号立即释放
    tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
    # 给程序绑定端口号
    tcp_server_socket.bind(("0.0.0.0", 6999))
    # 设置监听
    tcp_server_socket.listen(128)
    log.info("服务器开始监听端口号: 6999")

    try:
        while True:
            # 等待客户端建立连接的请求
            service_client_socket, ip_port = tcp_server_socket.accept()
            log.info(f"客户端的IP地址和端口号: {ip_port}")

            # 在单独的线程或进程中处理客户端连接,这里简化为直接调用处理函数
            handle_client(service_client_socket, ip_port)


    except KeyboardInterrupt:
        print("服务器接收到停止信号,正在关闭...")
    finally:
        # 关闭服务端的套接字(通常在实际应用中,这一步会在所有客户端连接都关闭后执行,但在这里我们直接响应中断信号)
        tcp_server_socket.close()

把注释加回来,可以心跳。

func = Function_mapping[AFN].get(Fn)
log.info(f"接口匹配成功!")
data , status = func(dict_data)
log.info(f'type:{type(data)}')
return data, status

在接收数据这里加上status后,连登录都报错了。有两种报错

  1. non-hexadecimal number found in fromhex() arg at position 63

  2. too many values to unpack (expected 2):

    这通常意味着你尝试将一个可迭代对象(如列表、元组等)解包到比该对象实际包含的元素数量更少的变量中。a, b = (1, 2, 3) # 这里会引发错误

意料之中,因为我还没修改函数返回值。

#先返回False,返回True后就会直接让输入接口编号了
return byte_resp_data, False

send_data , status = api.Message_parsing(recv_data)
# 准备发送的数据
if send_data:
	log.info(f'要发送的数据:{send_data}')
	print(f'要发送的数据:{send_data}')

	# 发送数据给客户端
	client_socket.send(send_data)
    log.info('发送成功!')
    print('发送成功!')

把登录和接收的数据修改后,可以成功登录了!

所以登录后的登录验证开始报错了,接下来把登录验证修改一下

return byte_resp_data, True

果然,修改后能成功进行登录验证了。

接下来试试能不能请求主动发送的接口。

试了一下,能发出去,但是收到的信息很。。。乱,SIM后面跟了两条心跳。

标签:log,info,socket,python,send,TCP,data,20240809,客户端
From: https://www.cnblogs.com/marverdol/p/18351248

相关文章

  • Python-和-PowerShell-协作教程-全-
    Python和PowerShell协作教程(全)原文:PowerShellandPythonTogether协议:CCBY-NC-SA4.0一、面向调查人员的PowerShell简介PowerShell提供了一个强大的获取引擎,可以从实时系统、服务器、外围设备、移动设备和数据驱动的应用程序(如ActiveDirectory)中获取大量信息。......
  • Blender-Python-API-教程-全-
    BlenderPythonAPI教程(全)原文:TheBlenderPythonAPI协议:CCBY-NC-SA4.0一、Blender界面本章讨论并定义Blender界面的组件。它作为我们在整个文本中讨论界面时使用的词汇的参考。我们将关注Python开发中最常用的接口组件,并为高效的Python脚本设置自定义接口。为......
  • 创造你自己的-Python-文本冒险-全-
    创造你自己的Python文本冒险(全)原文:MakeYourOwnPythonTextAdventure协议:CCBY-NC-SA4.0一、入门指南介绍你可能听过互联网上的口号,“学会编码!学会编码!”,并且您已经了解到Python是一个很好的起点…但是现在该怎么办呢?很多想编程的人不知道从何下手。你可以用代码创......
  • 面向忙碌的-Java-开发者的-Python-教程-全-
    面向忙碌的Java开发者的Python教程(全)原文:PythonfortheBusyJavaDeveloper协议:CCBY-NC-SA4.0一、语言让我们从了解Python与Java的不同之处开始我们的Python之旅。在下一章深入研究Python的语法之前,我将帮助你设置Python。Python是什么?Python是一种“......
  • python with 上下文管理器
    简介1、什么是上下文管理器?上下文管理器是一种实现了上下文管理协议(ContextManagementProtocol)的对象,它通过定义__enter__()和__exit__()两个特殊方法来实现资源的获取和释放。上下文管理器通常使用with语句进行调用,确保资源在使用完毕后能够被正确释放。python中上下文管理......
  • 用Python打造精彩动画与视频,9.2 从概念到成品的完整工作流程
     第九章:综合项目9.2从概念到成品的完整工作流程在前面的章节中,我们深入探讨了各种Python技术及其在动画与视频制作中的应用。在本章中,我们将综合运用这些技术,完成一个完整的项目——从初步概念到最终成品的工作流程。这一流程不仅包括技术实现,还涉及规划、设计、测试和发布......
  • 用Python打造精彩动画与视频,9.3 项目案例分享与反思
     第九章:综合项目9.3项目案例分享与反思在本节中,我们将分享几个成功的项目案例,并进行反思总结。这些案例将展示如何将前面所学的Python技术运用于实际项目中,同时我们将讨论项目中的挑战和解决方案,以及从中得到的经验教训。案例一:教育视频制作项目项目简介:本项目旨在为初学......
  • 为什么 True/False 在 Python 中要大写?
    所有成员都是骆驼案吧?为什么True/False而不是true/false,哪个更宽松?在Python中,True和False使用大写而不是小写,这与语言的禅宗(设计原则)和它们在Python中的特殊地位有关。让我们来分析一下:1.特殊地位:在Python中,True和False......
  • 如何使用 Python 从 Excel 工作表中读取正斜杠
    我有20多列的Excel工作表,如果我想选择不包含文本n/a的行,是否可以将n/a作为文本传递并找到它?我尝试过的代码是,''''将pandas导入为pd进口重新导入操作系统defextract_data(input_file):#读取输入的Excel文件df=pd.read_excel(input_file)#Checkif'......
  • TCP三次握手与四次挥手
    一、三次握手三次握手的主要目的是建立一个可靠的连接,确保两端的发送者和接收者都准备好进行数据传输。想象成你(客户端)想要通过电话与一个朋友(服务器)进行长时间的对话。在你们开始聊天之前,需要先确保彼此都准备好了。这个过程包括以下步骤: 1:SYN:客户端发送一个SYN(同步序列......