我一直在使用多个Raspberry Pi,Python和一些按钮/开关进行游戏。我的游戏需要一个中央服务器,该服务器向多个客户端发出命令。
我不是编程新手,而是Python和较低级网络通信的新手,在过去两天里,我一直迷失在如何精确编写服务器代码方面。
客户端程序是一个简单的socket.connect,然后等待发送数据。那里没有问题。
我很难确定确切的编写方式以及如何使服务器正常工作。
这是我目前的服务器代码:
import socket, time, sys
import threading
TCP_IP = ''
TCP_PORT = 8888
BUFFER_SIZE = 1024
CLIENTS = {}
clientCount = 0
def listener():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP,TCP_PORT))
s.listen(5)
while True:
conn, addr = s.accept()
print("new connection from:"+ str(addr))
#print(len(CLIENTS))
global clientCount
clientCount = clientCount+1
print (clientCount)
# register client
CLIENTS[conn.fileno()] = conn
def broadcast():
for client in CLIENTS.values():
client.send('this is a broadcats msg')
if __name__ == '__main__':
listener()
while clientCount > 0:
broadcast()
print(len(CLIENTS)) #print out the number of connected clients every 5s
time.sleep(5)
这是所需的流程:1.服务器启动并等待第一个或更多连接。我相信这个“服务器”应该在后台线程上运行吗?2.如果connectionCount > 0
启动主程序循环,则3.现在,主程序循环应仅显示已连接客户端的数量,并每5秒向所有客户端广播一条消息。
我有大约5个版本的服务器。我曾尝试过async,select.select和几种线程方法,但无法完全确定我寻求的行为。我应该将服务器置于后台线程中吗?如果是这样,如何广播到所有连接?
我唯一没有尝试过的就是Twisted,那是因为我无法在Windows中安装它……所以我暂时不考虑optino。如果有人在哪里进行指导,我将不胜感激!
更新资料
好的,根据@Armans的建议,我已经更新了代码,以便有一个服务器类,但它仍然执行相同的操作。
class server():
def __init__(self):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP,TCP_PORT))
s.listen(10)
while 1:
client_socket, addr = s.accept()
print ('Connected with ' + addr[0] + ':' + str(addr[1]))
global clientCount
clientCount = clientCount+1
print (clientCount)
# register client
CLIENTS[client_socket.fileno()] = client_socket
threading.Thread(target=self.handler, args=(client_socket, addr)).start()
def handler(self, client_socket, addr):
while 1:
data = client_socket.recv(BUFFER_SIZE)
print ('Data : ' + repr(data) + "\n")
data = data.decode("UTF-8")
def broadcast(self, message):
for c in self.CLIENTS:
c.send(message.encode("utf-8"))
if __name__ == '__main__':
s = server() #create new server listening for connections
while clientCount > 0:
s.broadcast('msg here')
print(len(CLIENTS)) #print out the number of connected clients every 5s
time.sleep(5)
我可以连接多个客户端,并且控制台显示以下内容:
Connected with 10.0.0.194:38406
1
Connected with 10.0.0.169:36460
2
但是“ while clientCount”循环中的代码永远不会运行。这是我被困住一段时间的区域,因此,如果您还有更多想法,我将乐意为您提供任何想法!
终于成功了!非常感谢@Arman为我指出正确的穿线方向。我终于感觉到我知道一切正常!
这是我完整的服务器和客户端代码。希望这可以通过master> client
setup帮助其他人。_broadcast()函数正在工作,因为您会看到它现在只广播静态msg,但这应该是一个简单的更新。
如果有人对代码清除有任何建议,请使用该代码作为示例的python最佳实践,我希望听到并了解更多。再次感谢SE!
##Client
import socket
import sys
import json
#vars
connected = False
#connect to server
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('10.0.0.158',8888))
connected = True
while connected == True:
#wait for server commands to do things, now we will just display things
data = client_socket.recv(1024)
cmd = json.loads(data) #we now only expect json
if(cmd['type'] == 'bet'):
bet = cmd['value']
print('betting is: '+bet)
elif (cmd['type'] == 'result'):
print('winner is: '+str(cmd['winner']))
print('payout is: '+str(cmd['payout']))
##Server
import socket, time, sys
import threading
import pprint
TCP_IP = ''
TCP_PORT = 8888
BUFFER_SIZE = 1024
clientCount = 0
class server():
def __init__(self):
self.CLIENTS = []
def startServer(self):
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP,TCP_PORT))
s.listen(10)
while 1:
client_socket, addr = s.accept()
print ('Connected with ' + addr[0] + ':' + str(addr[1]))
global clientCount
clientCount = clientCount+1
print (clientCount)
# register client
self.CLIENTS.append(client_socket)
threading.Thread(target=self.playerHandler, args=(client_socket,)).start()
s.close()
except socket.error as msg:
print ('Could Not Start Server Thread. Error Code : ') #+ str(msg[0]) + ' Message ' + msg[1]
sys.exit()
#client handler :one of these loops is running for each thread/player
def playerHandler(self, client_socket):
#send welcome msg to new client
client_socket.send(bytes('{"type": "bet","value": "1"}', 'UTF-8'))
while 1:
data = client_socket.recv(BUFFER_SIZE)
if not data:
break
#print ('Data : ' + repr(data) + "\n")
#data = data.decode("UTF-8")
# broadcast
for client in self.CLIENTS.values():
client.send(data)
# the connection is closed: unregister
self.CLIENTS.remove(client_socket)
#client_socket.close() #do we close the socket when the program ends? or for ea client thead?
def broadcast(self, message):
for c in self.CLIENTS:
c.send(message.encode("utf-8"))
def _broadcast(self):
for sock in self.CLIENTS:
try :
self._send(sock)
except socket.error:
sock.close() # closing the socket connection
self.CLIENTS.remove(sock) # removing the socket from the active connections list
def _send(self, sock):
# Packs the message with 4 leading bytes representing the message length
#msg = struct.pack('>I', len(msg)) + msg
# Sends the packed message
sock.send(bytes('{"type": "bet","value": "1"}', 'UTF-8'))
if __name__ == '__main__':
s = server() #create new server listening for connections
threading.Thread(target=s.startServer).start()
while 1:
s._broadcast()
pprint.pprint(s.CLIENTS)
print(len(s.CLIENTS)) #print out the number of connected clients every 5s
time.sleep(5)
我需要在火花中连接2个表。但是我首先过滤掉第二个表的一部分,而不是完全连接2个表: 我想在这种情况下使用广播连接。 Spark有一个参数,用于定义广播连接的最大表大小:: 配置在执行联接时将广播到所有工作节点的表的最大大小(以字节为单位)。通过将该值设置为-1,可以禁用广播。请注意,当前统计信息仅支持已运行命令ANALYZE TABLE COMPUTE statistics noscan的配置单元
问题内容: 有人可以解释和之间的确切区别吗? 在什么情况下我们必须使用每个Receiver类? 问题答案: 和之间只有一个区别。 当您收到内部广播方法时, 假设, BroadcastReceiver : 它 不保证 该 CPU将保持清醒 ,如果你启动一些长时间运行的进程。CPU可能会立即回到睡眠状态。 WakefulBroadcastReceiver : 这是 保证 该 CPU将保持清醒 ,直到你
我是套接字IO开发的新手。我想知道以下情况: > 支持的并发打开套接字数的最大限制? 为生产而微调节点服务器时需要注意的指导原则/额外的注意事项。 socket.io确保消息传递吗?还是送了就忘了?另外,在安装时是否有节点模块可以利用此特性? 如果socket.io不支持消息传递;如何确保消息被成功发送和接收到预定的人?
我目前正在使用SharedReferences跟踪通过AlarmManager启动的BroadcastReceiver中要执行工作的项列表。除了一个特定的场景外,一切都很好。当我触发一个新项目来执行工作时,让它完成工作,然后删除该项目(全部通过SharedReferences编辑),它在应用程序运行时工作得很好。当列表中没有任何内容,我打开任务管理器并终止应用程序时,该项突然出现在Broadcas
如何在Android中检测WIFI连接何时已建立? Android WIFI如何检测特定WIFI连接何时可用 广播接收器不工作(检测wifi是否连接) 还有更多...但可悲的是,我没有找到正确的答案。 我想做的事情是获取用户连接到网络的确切事件,然后得到一个好的方法来检测我是否可以做一个谷歌ping,或者检查是否有连接到互联网(只有WIFI,3G连接是不允许的),因为我现在使用的代码有时会失败..
本文向大家介绍Android中的广播和广播接收器代码实例,包括了Android中的广播和广播接收器代码实例的使用技巧和注意事项,需要的朋友参考一下 BroadcastReceiver不仅可以接收系统广播,也可接收自定义的广播 1.定义一个广播接收器 2.发送广播,定义好action标志,用Intent发送 3.注册只接收指定action的广播接收器 4.取消该广播接收器