查看: 6597|回复: 6

【懒兔子玩树莓】Python TCP编程

[复制链接]
  • TA的每日心情
    无聊
    2015-8-17 09:38
  • 签到天数: 361 天

    连续签到: 1 天

    [LV.8]以坛为家I

    发表于 2015-3-18 16:31:42 | 显示全部楼层 |阅读模式
    分享到:
    本帖最后由 懒兔子 于 2015-5-30 15:05 编辑

    树莓派 Python TCP编程

    TCP协议是网络通信领域使用最广泛的协议之一。

    和其他Linux下的编程方式一样,Python的TCP通信也可以基于Socket方式实现。TCP通信协议通过建立连接和应答来保证通信质量,它将通信设备分为Server和Client,两者的操作方式也有些区别。


    1. TCP Server和Client

    Server基本流程为:创建Socket -> 绑定IP和端口 -> 在绑定的IP和端口上监听连接请求 -> 接受Client发出的连接请求 -> 收发收据 -> 关闭连接。

    下面是一个简单的例子,实现了基本的TCP Server功能。


    1. import socket
    2. import time
    3. import sys

    4. HOST_IP = "137.58.230.162"
    5. HOST_PORT = 7654

    6. #创建Socket,SOCK_STREAM表示类型为TCP
    7. print("Starting socket: TCP...")
    8. socket_tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    9. #绑定IP和端口,并进行监听
    10. #137.58.230.162为本机IP,端口为7654
    11. print("TCP server listen @ %s:%d!" %(HOST_IP, HOST_PORT) )
    12. host_addr = (HOST_IP, HOST_PORT)
    13. socket_tcp.bind(host_addr)
    14. socket_tcp.listen(1)

    15. #接受Client发出的连接请求,返回值包含了Client的IP和端口
    16. socket_con, (client_ip, client_port) = socket_tcp.accept()
    17. print("Connection accepted from %s." %client_ip)

    18. #向Clinet发送数据
    19. socket_con.send("Welcome to RPi TCP server!")

    20. socket_tcp.close()
    复制代码

    Client对应的流程要简单的多:创建Socket -> 向服务器发出连接请求 -> 连接建立成 -> 收发收据 -> 关闭连接。

    代码如下:

    1. import socket   
    2. import time
    3. import sys
    4.    
    5. SERVER_IP = "137.58.230.162"
    6. SERVER_PORT = 7654
    7. #创建Socket,SOCK_STREAM表示类型为TCP
    8. print("Starting socket: TCP...")
    9. socket_tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    10. #向服务器发出连接请求,需要指定服务器IP和端口
    11. print("Connecting to server @ %s:%d..." %(SERVER_IP, SERVER_PORT))
    12. server_addr = (SERVER_IP, SERVER_PORT)
    13. socket_tcp.connect(server_addr)  

    14. #接收服务器发来的欢迎数据
    15. data = socket_tcp.recv(512)
    16. print("Server: %s" %data)

    17. socket_tcp.close()
    复制代码

    在树莓派上运行TCP Server,Client可以同时在树莓派上运行来测试通信,或者在其他网络设备上运行。当然,这种完成通信就直接关闭Socket的方法简单粗暴,实际的应用应当包含更完善的断开连接和异常处理机制。



    在树莓派上运行TCP Server


    在树莓派上运行TCP Client


    在PC上运行TCP Client


    2. TCP数据传输

    下面的代码实现了Server端和Client端的双向数据收发。其基本结构与之前的例子相同,但是多出了错误检测的部分。

    Server端的代码中,try…except…部分循环接收Client发来的数据,然后给出回应。程序一旦出现错误,如对方断开连接,就退出程序。

    1. import socket
    2. import time
    3. import sys

    4. HOST_IP = "137.58.230.162"
    5. HOST_PORT = 7654

    6. print("Starting socket: TCP...")
    7. host_addr = (HOST_IP, HOST_PORT)
    8. socket_tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    9. print("TCP server listen @ %s:%d!" %(HOST_IP, HOST_PORT) )
    10. socket_tcp.bind(host_addr)
    11. socket_tcp.listen(1)

    12. socket_con, (client_ip, client_port) = socket_tcp.accept()
    13. print("Connection accepted from %s." %client_ip)
    14. socket_con.send("Welcome to RPi TCP server!")

    15. print("Receiving package...")
    16. while True:
    17.     try:
    18.         data = socket_con.recv(512)  
    19.         if len(data)>0:
    20.             print("Received: %s" %data)
    21.             socket_con.send("OK!")
    22.             time.sleep(1)
    23.             continue
    24.     except Exception:  
    25.         socket_tcp.close()
    26.         sys.exit(1)
    复制代码

    Client端的代码增加了尝试连接部分,如果连接不成功报错,如服务器超时无响应,就等待一段时间再重新发起连接请求。

    1. import socket   
    2. import time
    3. import sys
    4.    
    5. SERVER_IP = "137.58.230.162"
    6. SERVER_PORT = 7654

    7. print("Starting socket: TCP...")
    8. server_addr = (SERVER_IP, SERVER_PORT)
    9. socket_tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    10. while True:  
    11.     try:
    12.         print("Connecting to server @ %s:%d..." %(SERVER_IP, SERVER_PORT))
    13.         socket_tcp.connect(server_addr)  
    14.         break  
    15.     except Exception:
    16.         print("Can't connect to server, try it latter!")
    17.         time.sleep(1)
    18.         continue  

    19. print("Receiving package...")  
    20. while True:
    21.     try:
    22.         data = socket_tcp.recv(512)  
    23.         if len(data)>0:
    24.             print("Received: %s" %data)
    25.             socket_tcp.send("Hello TCP!")
    26.             time.sleep(1)
    27.             continue
    28.     except Exception:  
    29.         socket_tcp.close()
    30.         socket_tcp = None
    31.         sys.exit(1)
    复制代码

    软件运行效果如图:

    Server端,收到Client的数据并回应


    Client端,收到Server发来的欢迎信息和回应


    回复

    使用道具 举报

  • TA的每日心情
    奋斗
    2018-10-29 22:48
  • 签到天数: 731 天

    连续签到: 1 天

    [LV.9]以坛为家II

    发表于 2015-3-18 23:29:47 | 显示全部楼层
    很实用的教程,受益匪浅!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2019-11-24 09:41
  • 签到天数: 549 天

    连续签到: 1 天

    [LV.9]以坛为家II

    发表于 2015-4-3 12:32:36 | 显示全部楼层
    good  job   !
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2020-2-14 12:16
  • 签到天数: 827 天

    连续签到: 1 天

    [LV.10]以坛为家III

    发表于 2015-4-3 15:31:20 | 显示全部楼层
    谢谢分享学习一下
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2016-12-8 15:01
  • 签到天数: 459 天

    连续签到: 1 天

    [LV.9]以坛为家II

    发表于 2015-4-4 18:22:13 | 显示全部楼层
    厉害~~~~~~~~~~~
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2024-8-14 08:56
  • 签到天数: 101 天

    连续签到: 2 天

    [LV.6]常住居民II

    发表于 2015-8-5 13:53:56 | 显示全部楼层

    谢谢分享学习一下
    回复 支持 反对

    使用道具 举报

  • TA的每日心情

    2023-7-25 22:49
  • 签到天数: 385 天

    连续签到: 1 天

    [LV.9]以坛为家II

    发表于 2015-8-14 13:48:46 | 显示全部楼层
    这是直接调用 API吗
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条



    手机版|小黑屋|与非网

    GMT+8, 2024-11-24 01:08 , Processed in 0.165263 second(s), 26 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.