6回答

0收藏

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

#开源分享 #开源分享 7203 人阅读 | 6 人回复 | 2015-03-18

本帖最后由 懒兔子 于 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发来的欢迎信息和回应


一只搞电子的懒兔子~~
分享到:
回复

使用道具 举报

回答|共 6 个

倒序浏览

沙发

suyong_yq

发表于 2015-3-18 23:29:47 | 只看该作者

很实用的教程,受益匪浅!
板凳

cnc2020

发表于 2015-4-3 12:32:36 | 只看该作者

good  job   !
地板

suoma

发表于 2015-4-3 15:31:20 | 只看该作者

谢谢分享学习一下
5#

zhaojunlin-1847508

发表于 2015-4-4 18:22:13 | 只看该作者

厉害~~~~~~~~~~~
6#

damiaa

发表于 2015-8-5 13:53:56 | 只看该作者


谢谢分享学习一下
7#

党国特派员

发表于 2015-8-14 13:48:46 | 只看该作者

这是直接调用 API吗
喜欢在构思妙想,电子产品DIY是工作,也是一种爱好。
您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

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