Reputation: 43
I've done a lot of research into working with the Sockets class in Python, but I'm having a difficult time understanding how to achieve a solution to my problem. Let me also be clear by saying that I have absolutely no experience with the Python language. The code that I've scraped together is from several other examples. It mainly works, I just have one last bug to figure out.
The idea is this script will run on a raspberry pi and that will be the Pi's sole purpose. Via TCP, you will request an image number, and the Pi will display that particular image full screen. Easy, right?
Again, everything works, except when the ethernet connection to the client is cut, or the client closes the connection. The script then enters a bad infinite loop, the CPU usage maxes out, and I have no choice but to physically power cycle the Pi. I need a way to ensure this won't happen and make a provision for the client to be able to reestablish a connection to this server in the event of a disconnect/network glitch/etc.
Here's what I have so far.
import sys
import pygame
import SocketServer
pygame.init()
screen = pygame.display.set_mode((0,0), pygame.FULLSCREEN, 0)
pygame.mouse.set_visible(False)
imagesequence = []
imagesequence.append(pygame.image.load("/home/pi/appfiles/image1.png")
imagesequence.append(pygame.image.load("/home/pi/appfiles/image2.png")
screensaver = []
screensaver.append(pygame.image.load("/home/pi/appfiles/screensaver1.png")
class MyTCPHandler(SocketServer.StreamRequestHandler):
def handle(self):
while True:
self.data = self.rfile.readline().strip()
isNum = False
try:
int(self.data)
isNum = True
except ValueError:
isNum = False
if isNum:
framenumber = int(self.data)
if framenumber >= 1 and framenumber <= len(imagesequence):
screen.blit(imagesequence[framenumber-1], (0,0))
pygame.display.flip()
elif framenumber >= 901 and framenumber <= 900+len(screensaver):
screen.blit(screensaver[framenumber-901], (0,0))
pygame.display.flip()
else:
if self.data == "q":
pygame.quit()
server.shutdown()
if __name__ == "__main__":
HOST, PORT = "192.168.1.51", 5050
SocketServer.TCPServer.allow_reuse_address = True
server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler)
server.serve_forever()
Quitting the script via TCP connection also doesn't work, but I'm not so concerned with that. Eventually, there will never be a reason to quit this.
Upvotes: 4
Views: 8757
Reputation: 178419
self.rfile.readline()
returns an empty string ''
when the socket connection is closed. Make sure to check it before applying .strip()
, though, since sending a whitespace-only line will look like an empty string after stripping whitespace.
import socketserver
class MyTCPHandler(SocketServer.StreamRequestHandler):
def handle(self):
while True:
self.data = self.rfile.readline()
if not self.data:
break
self.data = self.data.strip()
...
Upvotes: 2
Reputation: 180
After relentless code digging, I cannot answer the first part. It looks like there is no way at this high level for you to detect a socket closing. Look into the (out of favor, I think, but perfectly usable) asyncore and asynchat modules.
As for the second part, you need to break from the loop on receiving a 'q'.
Tongue in cheek code sample:
break
Upvotes: 0