i am losing messages in my tornado chat and i do not known how to detect when the message wasn't sent and to send the message again
there is any way to detect when the conexion get lost? and when the conexión restart send the message
this is my code
def get(self):
try:
json.dumps(MessageMixin.cache)
except KeyError:
raise tornado.web.HTTPError(404)
class MessageMixin(object):
waiters = {}
cache = {}
cache_size = 200
def wait_for_messages(self,cursor=None):
t = self.section_slug
waiters = self.waiters.setdefault(t, [])
result_future = Future()
waiters.append(result_future)
return result_future
def cancel_wait(self, future):
t = self.section_slug
waiters = self.waiters.setdefault(t, [])
waiters.remove(future)
# Set an empty result to unblock any coroutines waiting.
future.set_result([])
def new_messages(self, message):
t = self.section_slug
#cache = self.cache.setdefault(t, [])
#print t
#print self.waiters.setdefault(t, [])
waiters = self.waiters.setdefault(t, [])
for future in waiters:
try:
if message is not None:
future.set_result(message)
except Exception:
logging.error("Error in waiter callback", exc_info=True)
waiters = []
#self.cache.extend(message)
#if len(self.cache) > self.cache_size:
#self.cache = self.cache[-self.cache_size:]
class MessageNewHandler(MainHandler, MessageMixin):
def post(self, section_slug):
self.section_slug = section_slug
post = self.get_argument("html")
idThread = self.get_argument("idThread")
isOpPost = self.get_argument("isOpPost")
arg_not = self.get_argument("arg")
type_not = self.get_argument("type")
redirect_to = self.get_argument("next", None)
message= {"posts": [post],"idThread": idThread,"isOpPost": isOpPost,
"type": type_not,"arg_not": arg_not}
if redirect_to:
self.redirect(redirect_to)
else:
self.write(post)
self.new_messages(message)
class MessageUpdatesHandler(MainHandler, MessageMixin):
#gen.coroutine
def post(self, section_slug):
self.section_slug = section_slug
try:
self.future = self.wait_for_messages(cursor=self.get_argument("cursor", None))
data = yield self.future
if self.request.connection.stream.closed():
return
self.write(data)
except Exception:
raise tornado.web.HTTPError(404)
def on_connection_close(self):
self.cancel_wait(self.future)
class Application(tornado.web.Application):
def __init__(self):
handlers = [
(r"/api/1\.0/stream/(\w+)", MessageUpdatesHandler),
(r"/api/1\.0/streamp/(\w+)", MessageNewHandler)
]
tornado.web.Application.__init__(self, handlers)
def main():
tornado.options.parse_command_line()
app = Application()
port = int(os.environ.get("PORT", 5000))
app.listen(port)
tornado.ioloop.IOLoop.instance().start()
if __name__ == "__main__":
main()
In the original chatdemo, this is what the cursor parameter to wait_for_messages is for: the browser tells you the last message it got, so you can send it every message since then. You need to buffer messages and potentially re-send them in wait_for_messages. The code you've quoted here will only send messages to those clients that are connected at the time the message came in (and remember that in long-polling, sending a message puts the client out of the "waiting" state for the duration of the network round-trip, so even when things are working normally clients will constantly enter and leave the waiting state)
Related
im running a chat app on my computer and i tried to send a message and this ERROR accured. it suppose to send a " will joind the chat" and another message " connected to server" after that i should send my message to the group and it didnt worked.
any ideas?
import kivy
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
import socket
import threading
kivy.require("1.9.0")
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
class MyRoot(BoxLayout):
def __init__(self):
super(MyRoot, self).__init__()
def send_message(self):
client.send(f"{self.nickname_text.text}: {self.message_text.text}".encode('utf-8'))
def connect_to_server(self):
if self.nickname_text != "":
client.connect((self.ip_text.text, 9999))
message = client.recv(1024).decode('utf-8')
if message == "NICK":
client.send(self.nickname_text.text.encode('utf-8'))
self.send_btn.disabled = False
self.message_text.disabled = False
self.connect_btn.disabled = True
self.ip_text.disabled = True
self.make_invisible(self.connection_grid)
self.make_invisible(self.connect_btn)
thread = threading.Thread(target=self.receive)
thread.start()
def make_invisible(self, widget):
widget.visible = False
widget.size_hint_x = None
widget.size_hint_y = None
widget.height = 0
widget.width = 0
widget.text = ""
widget.opacity = 0
def receive(self):
stop = False
while not stop:
try:
message = client.recv(1024).decode('utf-8')
self.chat_text.text += message + "\n"
except:
print("ERROR")
client.close()
stop = True
class TraboChat(App):
def build(self):
return MyRoot()
trabo_chat = TraboChat()
trabo_chat.run()
serve.py:
import socket
import threading
HOST = socket.gethostbyname(socket.gethostname())
PORT = 9999
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((HOST, PORT))
server.listen()
clients = []
nicknames = []
def broadcast(message):
for client in clients:
client.send(message)
def handle_connection(client):
stop = False
while not stop:
try:
message = client.recv(1024)
broadcast(message)
except:
index = clients.index(client)
clients.remove(client)
nickname = nicknames[index]
nicknames.remove(nickname)
broadcast(f"{nickname} left the chat!".encode('utf-8'))
stop = True
def main():
print("server is running..")
while True:
client, addr = server.accept()
print(f"connected to {addr}")
client.send("NICK".encode('utf-8'))
nickname = client.recv(1024).decode('utf-8')
nicknames.append(nickname)
clients.append(client)
print(f"Nickname is {nickname}")
broadcast(f"{nickname} join the chat!")
client.send("You are now connected".encode('utf-8'))
thread = threading.Thread(target=handle_connection, args=(client,))
if name == 'main':
main()
I have created an approximate time synchronizer to sync stereo camera images are GPS. The time synchronizer does not enter the callback. I have already tried playing around with slop and queue_size parameters.
class sorghum_gps:
def __init__(self,arg1):
self.bridge = CvBridge()
self.image_sub0 = message_filters.Subscriber("/cam0/image_raw",Image)
self.image_sub1 = message_filters.Subscriber("/cam1/image_raw",Image)
self.gps_sub = message_filters.Subscriber("/fix",NavSatFix)
self.ts = message_filters.ApproximateTimeSynchronizer([self.image_sub0,self.image_sub1, self.gps_sub],5,1)
self.ts.registerCallback(self.callback0)
def callback0(self,data1, data2, data3):
try:
cv_image0 = self.bridge.imgmsg_to_cv2(data1, "bgr8")
cv_image1 = self.bridge.imgmsg_to_cv2(data2, "bgr8")
print('got_data')
except CvBridgeError as e:
print(e)
def call1(self, data):
print(data)
def main(args):
print(args[1], 'RUNNING')
rospy.init_node('node_gps',anonymous=True)
gp = sorghum_gps(args)
try:
rospy.spin()
except KeyboardInterrupt:
print("Shutting down")
cv2.destroyAllWindows()
if __name__ == '__main__':
main(sys.argv)
Here are the details of the bag file I am trying to sync
types: sensor_msgs/Image [060021388200f6f0f447d0fcd9c64743]
sensor_msgs/NavSatFix [2d3a8cd499b9b4a0249fb98fd05cfa48] topics: /fix 7748 msgs :
sensor_msgs/NavSatFix
/cam0/image_raw 1942 msgs : sensor_msgs/Image
/cam1/image_raw 1942 msgs : sensor_msgs/Image
How can I close a WebSocket connection? The example on the documentation works if you want to close it immediately.
But how about the following case: I want to close the connection when some condition occurs in the future. For instance, when I receive a certain message from the client.
def indexWS = WebSocket.using[String] {
request => {
var channel: Option[Concurrent.Channel[String]] = None
var outEnumerator: Enumerator[String] = Concurrent.unicast(c => channel = Some(c))
val myIteratee: Iteratee[String, Unit] = Iteratee.foreach[String] {gotString => {
// received a string from the client
if (gotString == "close_me") {
// outEnumerator = Enumerator.eof // doesn't work
// outEnumerator >>> Enumerator.eof // doesn't work
}
}}
(myIteratee, outEnumerator)
}
}
Thank you for your help!
I got it: I had to go through the channel that I opened at
var outEnumerator: Enumerator[String] = Concurrent.unicast(c => channel = Some(c))
and the commented out block would become
if (gotString == "close_me") {
channel.foreach(_.eofAndEnd())
}
which will push an EOF through the enumerator and close the connection.
How do one debug the connection from a provider to Apple push notification server?
I'm using a library called PyAPNs (github repo) and have the code below:
from apns import APNs, Payload
print "start"
apns = APNs(use_sandbox=True, cert_file='apns-prod.pem', key_file='apns-prod.pem')
# Send a notification
token_hex = '*******'
payload = Payload(alert="Hello World!", sound="default", badge=1)
apns.gateway_server.send_notification(token_hex, payload)
# Get feedback messages
for (token_hex, fail_time) in apns.feedback_server.items():
print token_hex
print fail_time
print "end"
The application is registered to receive RemoteNotification an everything looks okey under notification settings in the iPhone. But not notifications shows up.
My questions here how can I debug this. When running the script I don't get any errors and the apns.feedback_server.items is empty. I've tried to print the buffer from the feedback serve, but nothing.
Is there a way to see what's happening in the SSL socket? Or get some response from apples servers?
..fredrik
EDIT
I solved the problem. The issues was with the token_hex. I used the identifier number from the xcode organizer and not the token generated when registering the application.
USE THIS CODE:
#!/usr/bin/python2.7
import socket
import ssl
import json
import struct
import argparse
APNS_HOST = ( 'gateway.sandbox.push.apple.com', 2195 )
class Payload:
PAYLOAD = '{"aps":{${MESSAGE}${BADGE}${SOUND}}}'
def __init__(self):
pass
def set_message(self, msg):
if msg is None:
self.PAYLOAD = self.PAYLOAD.replace('${MESSAGE}', '')
else:
self.PAYLOAD = self.PAYLOAD.replace('${MESSAGE}', '"alert":"%s",' % msg)
def set_badge(self, num):
if num is None:
self.PAYLOAD = self.PAYLOAD.replace('${BADGE}', '')
else:
self.PAYLOAD = self.PAYLOAD.replace('${BADGE}', '"badge":%s,' % num)
def set_sound(self, sound):
if sound is None:
self.PAYLOAD = self.PAYLOAD.replace('${SOUND}', '')
else:
self.PAYLOAD = self.PAYLOAD.replace('${SOUND}', '"sound":"%s",' % sound)
def toString(self):
return (self.PAYLOAD.replace('${MESSAGE}','').replace('${BADGE}','').replace('${SOUND}',''))
def connectAPNS(host, cert):
ssl_sock = ssl.wrap_socket( socket.socket( socket.AF_INET, socket.SOCK_STREAM ), certfile = cert )
ssl_sock.connect( APNS_HOST )
return ssl_sock
def sendNotification(sslSock, device, message, badge, sound):
payload = Payload()
payload.set_message(message)
payload.set_badge(badge)
payload.set_sound(sound)
payloadAsStr = payload.toString()
format = '!BH32sH%ds' % len(payloadAsStr)
binaryDeviceToken = device.replace(' ','').decode('hex')
binaryNotification = struct.pack( format, 0, 32, binaryDeviceToken, len(payloadAsStr), payloadAsStr )
print ("sending payload: ["+payloadAsStr+"] as binary to device: ["+device+"]")
sslSock.write(binaryNotification)
def printUsageAndExit():
print("msg2ios - Version 0.1\nmsg2IOS.py -d <device> -m <message> -s[plays sound] -b <badgeint> -c <certBundlePath>")
exit(1)
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('-d', '--device')
parser.add_argument('-m', '--message')
parser.add_argument('-s', '--sound')
parser.add_argument('-b', '--badge')
parser.add_argument('-c', '--cert')
args = parser.parse_args()
if (args.device is None) or ((args.message is None) and (args.sound is None) and (args.badge is None)) or (args.cert is None):
printUsageAndExit()
sslSock = connectAPNS(APNS_HOST, args.cert)
sendNotification(sslSock, args.device, args.message, args.badge, args.sound)
sslSock.close()
I have made a class in python 3 and i can't figure why i can't send the information for the server to client. Server and client are using the same class.
class mysocket:
receive_string_buffer_len = 0
active_instance = 0
def __init__(self):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.receive_string_buffer = ''
self.send_string_buffer = ''
self.host = 'localhost'
self.port = 30000 + self.active_instance
self.active_instance += 1
def connect(self):
self.sock.connect((self.host,self.port))
def mysend(self):
try:
sent = self.sock.send(self.send_string_buffer)
except socket.error:
print('socket connection broken')
def myreceive(self):
try:
self.receive_string_buffer = self.sock.recv(512)
except socket.error:
print('socket connection broken')
finally: return self.receive_string_buffer
Client code:
Client_socket1 = mysocket()
Client_socket1.connect()
print(Client_socket1.myreceive().decode('ascii'))
Server code:
Server_socket1 = mysocket()
Server_socket1.bind(('', 30000))
Server_socket1.listen(1)
client1, add = Server_socket1.accept()
Server_socket1.send_string_buffer = ' alo '
Server_socket1.mysend().encode('ascii')
The problem is that it's not working. I am new to python programing and new to sockets so if i done stupid mistakes please tell me .
Thanks to anyone that will read this.
You are sending data on the listening socket instead of the client-server socket returned by accept().
Rgds,
Martin
I dont think "Server_socket1.mysend().encode('ascii')" is valid especially since mysend() doesn't return anything to encode (and you do nothing with return value from encode()). Also you need to encode your data before it can be sent.
I think you will find asynchat module much easier to handle sockets. Just sub class it like:
import threading
class mysocket(asynchat.async_chat):
terminator = b'\n'
def __init__(self,sock=None):
asynchat.async_chat.__init__(self,sock)
self.create_socket()
self.connect(('127.0.0.1',6667))
def handle_connect(self):
pass
def handle_close(self):
pass
def collect_incoming_data(self, data):
pass
def found_terminator(self):
pass
def sockwrite(self,text=None):
# Avoid conflict with text=''
if (text == None):
text = ''
text += '\n'
self.sendall(bytes(text,'latin-1'))
chatsock = {}
def main():
chatsock['a'] = mysocket()
socketloop = threading.Thread(target=asyncore.loop, daemon=1)
socketloop.start()
while True:
pass
if __name__ == "__main__":
main()