我刚刚开始编程python。 我的目标是建立具有三个屏幕的数码相框。因此,我使用3个Raspis,每个监视器一个。 为了与这些Raspis进行通信,我需要对服务器和客户端进行编程。
对于第一个测试,我想构建一个服务器,该服务器能够向/从多个客户端发送和接收消息。 因此,我从一些套接字教程开始,并创建了以下程序。
服务器类(TcpServer.py)
class TcpServer:
clients = []
serverIsRunning = 0
port = 0
def __init__(self, port):
self.port = port
self.serverIsRunning = 0
self.serverRunning = 0
def startServer (self):
print("start Server...")
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server.bind(("", self.port))
self.server.listen(1)
self.serverRunning = 1
while self.serverRunning:
read, write, oob = select.select([self.server] + self.clients, [], [])
for sock in read:
if sock is self.server:
client, addr = self.server.accept()
self.clients.append(client)
print ("+++ Client ", addr[0], " verbunden")
else:
nachricht = sock.recv(1024)
ip = sock.getpeername()[0]
if nachricht:
print (ip, nachricht)
else:
print ("+++ Verbindung zu ", ip , " beendet")
sock.close()
self.clients.remove(sock)
for c in self.clients:
c.close()
self.clients.remove(c)
self.server.close()
def send(self, message):
message = message.encode()
self.server.send(message)
客户端类(TcpClient.py)
import socket
class TcpClient:
def __init__(self, ip, port):
self.serverAdress = (ip, port)
self.connected = 0
self.connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.connection.connect(self.serverAdress)
print ("connectet to ", self.serverAdress)
def send(self, message):
message = message.encode()
self.connection.send(message)
服务器:
import threading
import TcpServer
tcpServer = TcpServer.TcpServer(50000)
threadTcpServer = threading.Thread(target = tcpServer.startServer)
threadTcpServer.start()
while True:
tcpServer.send(input("Nachricht eingeben: "))
客户:
import threading
import TcpClient
tcpClient = TcpClient.TcpClient("192.168.178.49", 50000)
while True:
tcpClient.send(input("Nachricht eingeben: "))
我可以将消息从客户端发送到服务器,但是当我要将消息从服务器发送到客户端时,会产生以下错误:
BrokenPipeError:[Errno 32]管道损坏
我认为这是因为服务器线程在等待传入消息时阻塞了套接字。但是我不知道该如何处理。 如何对可以发送和接收消息的服务器进行编程?你能推荐一个教程吗?我没有找到描述我的问题解决方案的教程。
编辑:
现在我试图用socketserver库解决问题,但是我仍然无法解决可能的问题。 这是服务器的新代码:
import socketserver
import threading
import time
class MyTCPHandler(socketserver.BaseRequestHandler):
"""
The RequestHandler class for our server.
It is instantiated once per connection to the server, and must
override the handle() method to implement communication to the
client.
"""
def handle(self):
# self.request is the TCP socket connected to the client
self.data = self.request.recv(1024).strip()
print("{} wrote:".format(self.client_address[0]))
print(self.data)
# just send back the same data, but upper-cased
self.request.sendall(self.data.upper())
if __name__ == "__main__":
HOST, PORT = "localhost", 9999
# Create the server, binding to localhost on port 9999
server = socketserver.TCPServer((HOST, PORT), MyTCPHandler)
# Activate the server; this will keep running until you
# interrupt the program with Ctrl-C
threadTcpServer = threading.Thread(target = server.serve_forever)
threadTcpServer.start()
print("server started")
time.sleep(10)
print("sending Data")
server.request.sendall("Server is sending...")
它会产生错误:
AttributeError:“ TCPServer”对象没有属性“ request”
我的目标是编写一个带有线程的服务器,该线程既可以接收数据又可以从另一个线程发送数据。 即使只有一个插槽,这是否有可能?
答案 0 :(得分:0)
您应该使用提供的socketserver而不是编写所有套接字的处理并选择etc。
您的代码有多个问题-
1-服务器正在尝试写入侦听套接字!客户端通信套接字是您从accept()调用获得的套接字,而这是您用于读写的套接字。
2-客户端正在发送数据并立即完成,但是它实际上应该等待得到响应。否则,python / OS将在程序完成后立即关闭客户端套接字,并且通常在服务器获得响应之前。
答案 1 :(得分:0)
我相信使用Handler代码,您既可以接收服务器上客户端发送的数据,又可以将某些数据从Handler发送回客户端?您必须已经了解,除非有客户端连接,否则服务器无法发送任何数据?
现在,要从“另一个”线程向客户端(或多个客户端)发送数据,您将需要一种方法来使处理程序对象或客户端套接字(在处理程序对象内部以def predict():
os.system('notepad cmnd.txt')
subprocess.call(['C:/Windows/System32/bash.exe'])
print(file_contents)
label = Label(master, text=file_contents)
#subprocess.call(['c:/users/hp/open.py'])
label.pack()
可用) “另一个”线程。
一种方法是重写self.request
方法并将def __init__(self, request, client_address, server):
对象的引用保存在全局列表中。请记住,将以下操作作为被覆盖的 init -
this
一旦所有客户端处理程序都位于全局列表中,就可以根据需要从任何线程轻松地写入所有客户端。您必须阅读有关同步(锁)的知识,并了解从多个线程使用相同的对象/套接字会在您的应用程序中造成一些逻辑/数据问题。
您还需要担心并编写代码的另一件事是,每当客户端关闭连接时,都会清理此全局列表。