Python library providing an implementation of the WebSocket protocol defined in RFC 6455.
Read the documentation for more information.
You can also join the ws4py mailing-list to discuss the library.
pip install ws4py
WebSocket client and server library for Python 2 and 3 as well as PyPy (ws4py 0.5.1)
Home Page: https://ws4py.readthedocs.org/en/latest/
License: BSD 3-Clause "New" or "Revised" License
Python library providing an implementation of the WebSocket protocol defined in RFC 6455.
Read the documentation for more information.
You can also join the ws4py mailing-list to discuss the library.
pip install ws4py
I am having followin issue:
File "/usr/local/lib/python2.6/dist-packages/ws4py/server/wsgi/middleware.py", line 117, in call
environ.get('wsgi.input')._sock),
AttributeError: 'Input' object has no attribute '_sock'
I search Input class of pywsgi getevent and did not found _sock function.
os: mac osx 10.6.2
chrome: 16.0.912.41 beta
ws4py: master
issue:
when use test with echo client , chrome console report server return 400 status code.
client test code:
<script type="text/javascript"> window.onload = function() { var ws_uri = "ws://localhost:9000"; if ("WebSocket" in window) { webSocket = new WebSocket(ws_uri); } else { // Firefox 7/8 currently prefixes the WebSocket object webSocket = new MozWebSocket(ws_uri); } webSocket.onmessage = function(e) { console.log("Got echo: " + e.data); } } </script>Is it possibly/easy to use ws4py with the Python standard modules SocketServer/BaseRequestHandler? If we are able to create such an example and/or server submodule, are there any interest in including that in the ws4py project?
As per the final spec (http://tools.ietf.org/html/rfc6455) all frames from the client must be masked. Currently control frames aren't being masked.
I'm trying to write a gunicorn worker class for the gevent-server (along the lines of the one offered by the gevent-websocket library
. I find the flow of the gevent-server example difficult to follow.
For instance, what is the purpose of this line https://github.com/Lawouach/WebSocket-for-Python/blob/master/example/echo_gevent_server.py#L47 when the handler_class
has already been set to UpgradableWSGIHandler
?
Also, what is the difference between UpgradableWSGIHandler
and WebSocketUpgradeMiddleware
.
The latest version (0.1.5) is not downloadable from http://www.defuze.org/oss/ws4py/ws4py-0.1.5.tar.gz (says 403 Forbidden). So ws4py is not installable through pypi.
I am using geventclient.py which subclasses WebSocketClient in threadedclient.py. The client connects and waits for a message. If the server sends a message and immediately closes the websocket, the client goes into an infinite loop. It happens in threadedclient.py in the _receive() method. Basically, there is a socket recv() command which returns "" indicating that the server has closed. But the _receive() method does not close, and calls socket recv() again. Here is the first part of the function with my patch, which fixes the problem in my limited tests.
def _receive(self):
next_size = 2
try:
self.sock.setblocking(1)
while self.running:
if self.__buffer:
bytes, self.__buffer = self.__buffer[:next_size], self.__buffer[next_size:]
else:
bytes = self.read_from_connection(next_size)
######### patch start
if bytes is None or len(bytes) == 0:
self.server_terminated = True
self.running = False
break
######### patch end
with self._lock:
s = self.stream
next_size = s.parser.send(bytes)
According to the standard draft 10 that the README says this server conforms to, the Upgrade header should be handled case-insensitively. Currently it is handled case-sensitively.
middleware.py:
def __call__(self, environ, start_response):
# Initial handshake validation
try:
if 'websocket' not in environ.get('upgrade.protocol', ''):
raise HandshakeError("Upgrade protocol is not websocket")
When running geventserver with gevent 1.0, exception occurs
Traceback (most recent call last):
File "build/bdist.macosx-10.7-intel/egg/gevent/pywsgi.py", line 449, in handle_one_response
self.run_application()
File "ws4py/server/geventserver.py", line 64, in run_application
self.result = self.application(self.environ, start_response_for_upgrade)
File "ws4py/server/wsgi/middleware.py", line 127, in call
start_response("101 Web Socket Hybi Handshake", headers)
File "ws4py/server/geventserver.py", line 54, in start_response_for_upgrade
self.wfile.writelines(towrite)
AttributeError: 'UpgradableWSGIHandler' object has no attribute 'wfile'
gevent.pywsgi.WSGIHandler no longer uses attribute wfile.
Here is my fix:
geventserver.py, line 54
self.headers_sent = True # otherwise, write() will send its own headers
for data in towrite:
write(data)
Something doesn't look right at the end of client/init.py. Is the following correct? Thanks.
diff --git a/ws4py/client/__init__.py b/ws4py/client/__init__.py
index fd6a155..61ed2a3 100644
--- a/ws4py/client/__init__.py
+++ b/ws4py/client/__init__.py
@@ -137,10 +137,10 @@ class WebSocketBaseClient(object):
if not binary:
self.write_to_connection(self.stream.text_message(bytes).fragment(first=first, mask=True))
else:
- self.write_to_connection(self.stream.binary_message(payload).fragment(first=first, mask=True))
+ self.write_to_connection(self.stream.binary_message(bytes).fragment(first=first, mask=True))
bytes = chunk
first = False
if not binary:
self.write_to_connection(self.stream.text_message(bytes).fragment(last=True, mask=True))
else:
- self.write_to_connection(self.stream.text_message(bytes).fragment(last=True, mask=True))
+ self.write_to_connection(self.stream.binary_message(bytes).fragment(last=True, mask=True))
By implicitly calling monkey.patch_all() in the gevent client, you are making the assumption that the code that uses your library wants the stdlib to be completely patched.
This may lead to locking issues & conflicts depending on the execution environment.
I would suggest removing that call and let the library users decide what they want to do
The current logic at ws4py/server/cherrypyserver.py:125 will only accept
Connection: Upgrade
during the initial handshake to upgrade HTTP to a websocket, but Firefox 7.0 OSX sends
Connection:keep-alive, Upgrade
Cheers,
Tim
We've been unable to run a CherryPy websocket server and then connect to it with the ws4py.client.threadedclient library without seeing unexpected connection closes and exceptions. This even happens with the example CherryPy echo client / server code. To reproduce, you can enter the following commands in a console:
python2.7 -m virtualenv --no-site-packages env
source env/bin/activate
pip install http://www.defuze.org/oss/ws4py/ws4py-0.2.1.tar.gz
pip install http://download.cherrypy.org/cherrypy/3.2.2/CherryPy-3.2.2.tar.gz
git clone https://github.com/Lawouach/WebSocket-for-Python.git
python WebSocket-for-Python/example/echo_cherrypy_server.py
and then in another console in the same directory type:
source env/bin/activate
python WebSocket-for-Python/example/echo_client.py
and you'll see the following output
0
25
50
75
100
125
150
175
=> 708 ####################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################
=> 0
=> 25 *************************
=> 50 **************************************************
=> 75 ***************************************************************************
=> 100 ****************************************************************************************************
=> 125 *****************************************************************************************************************************
=> 150 ******************************************************************************************************************************************************
=> 175 *******************************************************************************************************************************************************************************
Closed down 1006 Going away
Exception in thread WebSocketClient:
Traceback (most recent call last):
File "/usr/local/lib/python2.7/threading.py", line 552, in __bootstrap_inner
self.run()
File "/usr/local/lib/python2.7/threading.py", line 505, in run
self.__target(*self.__args, **self.__kwargs)
File "/home/eli/temp/ws4py/env/lib/python2.7/site-packages/ws4py/websocket.py", line 230, in run
if not process(bytes):
File "/home/eli/temp/ws4py/env/lib/python2.7/site-packages/ws4py/websocket.py", line 265, in process
self.reading_buffer_size = s.parser.send(bytes) or DEFAULT_READING_SIZE
File "/home/eli/temp/ws4py/env/lib/python2.7/site-packages/ws4py/streaming.py", line 258, in receiver
is_valid, end_on_code_point, _, _ = utf8validator.validate(reason)
File "/home/eli/temp/ws4py/env/lib/python2.7/site-packages/ws4py/utf8validator.py", line 108, in validate
self.state = Utf8Validator.UTF8VALIDATOR_DFA[256 + (self.state << 4) + Utf8Validator.UTF8VALIDATOR_DFA[ba[i]]]
TypeError: list indices must be integers, not str
So it looks like the data transfer works for awhile, but then shuts down before all of the data can be sent back and forth. This did not happen in previous versions; we're still using ws4py 0.1.3 for our development because this doesn't seem to happen with that release.
We have reproduced this issue on both Python 2.6 and 2.7, and it occurs on both OSX and Ubuntu. Please let me know if there's anything else I can do to help.
sphinx-build -b html -d _build/doctrees . _build/html
Making output directory...
Running Sphinx v1.1.3
loading pickled environment... not yet created
building [html]: targets for 10 source files that are out of date
updating environment: 10 added, 0 changed, 0 removed
reading sources... [ 70%] ws4py
Sphinx error:
'utf8' codec can't decode byte 0xbe in position 146: invalid start byte
make: *** [html] Error 1
I use ws4py with Cherrypy (the plugin and the tool provided).
It works just fine most of the time, but sometimes I have in my log a traceback like that. I didn't remove any line from it, more explanations are given below:
Exception in thread WebSocket client at _..**.**_:56741:
Traceback (most recent call last):
File "/usr/local/lib/python3.3/threading.py", line 639, in _bootstrap_inner
self.run()
File "/usr/local/lib/python3.3/threading.py", line 596, in run
self._target(_self._args, *_self._kwargs)
File "/usr/local/lib/python3.3/site-packages/ws4py-0.2.5-py3.3.egg/ws4py/websocket.py", line 291, in run
if not process(bytes):
File "/usr/local/lib/python3.3/site-packages/ws4py-0.2.5-py3.3.egg/ws4py/websocket.py", line 343, in process
self.received_message(s.message)
File "/home/vlegoff/pa-poc2/scripts/../plugins/websocket/handler.py", line 86, in received_message
function(**args)
File "/home/vlegoff/pa-poc2/scripts/../bundles/chat/websockets/chat.py", line 32, in handle_setpseudo
self.send_to_connected(welcome, self)
File "/home/vlegoff/pa-poc2/scripts/../bundles/chat/websockets/chat.py", line 58, in send_to_connected
ws_handler.send_message(message, escape=escape)
File "/home/vlegoff/pa-poc2/scripts/../bundles/chat/websockets/chat.py", line 69, in send_message
self.send_JSON("message", message=message)
File "/home/vlegoff/pa-poc2/scripts/../plugins/websocket/handler.py", line 110, in send_JSON
self.send_text(text)
File "/home/vlegoff/pa-poc2/scripts/../plugins/websocket/handler.py", line 101, in send_text
self.send(msg)
File "/usr/local/lib/python3.3/site-packages/ws4py-0.2.5-py3.3.egg/ws4py/websocket.py", line 219, in send
message_sender = self.stream.binary_message if binary else self.stream.text_message
AttributeError: 'NoneType' object has no attribute 'text_message'
The almost last lines are part of my application: I have a WebSocketHandler (the Chat class inherited from WebSocket defined in ws4py). The goal is to send a message to one of the connected client and it finally crashes on the WebSocket.send method.
Do you know why this happens and how to fix it? Is it a ws4py bug or a wrong usage in my application?
When creating WebSockets with a WSS:// URL the TornadoWebSocketClient class fails to connect. The following is the code snippet that I'm using to test the functionality.
from ws4py.client.tornadoclient import TornadoWebSocketClient
import tornado.ioloop
c = TornadoWebSocketClient("wss://127.0.0.1:8888/")
c.connect()
tornado.ioloop.IOLoop.instance().start()
The server is a simple demo Tornado Server with SSL enabled. The error on the server side is the following
WARNING:root:SSL Error on 8: [Errno 1] _ssl.c:490: error:1407609C:SSL routines:SSL23_GET_CLIENT_HELLO:http request
The error on the client side is the following
WARNING:root:Read error on 3: [Errno 104] Connection reset by peer
ERROR:root:Uncaught exception, closing connection.
Traceback (most recent call last):
File "/usr/local/lib/python2.6/dist-packages/tornado/iostream.py", line 304, in wrapper
callback(*args)
File "/usr/local/lib/python2.6/dist-packages/ws4py-0.2.0-py2.6.egg/ws4py/client/tornadoclient.py", line 34, in __handshake_sent
self.io.read_until("\r\n\r\n", self.__handshake_completed)
File "/usr/local/lib/python2.6/dist-packages/tornado/iostream.py", line 160, in read_until
self._check_closed()
File "/usr/local/lib/python2.6/dist-packages/tornado/iostream.py", line 535, in _check_closed
raise IOError("Stream is closed")
IOError: Stream is closed
ERROR:root:Exception in callback <tornado.stack_context._StackContextWrapper object at 0x99e89dc>
Traceback (most recent call last):
File "/usr/local/lib/python2.6/dist-packages/tornado/ioloop.py", line 399, in _run_callback
callback()
File "/usr/local/lib/python2.6/dist-packages/tornado/iostream.py", line 304, in wrapper
callback(*args)
File "/usr/local/lib/python2.6/dist-packages/ws4py-0.2.0-py2.6.egg/ws4py/client/tornadoclient.py", line 34, in __handshake_sent
self.io.read_until("\r\n\r\n", self.__handshake_completed)
File "/usr/local/lib/python2.6/dist-packages/tornado/iostream.py", line 160, in read_until
self._check_closed()
File "/usr/local/lib/python2.6/dist-packages/tornado/iostream.py", line 535, in _check_closed
raise IOError("Stream is closed")
IOError: Stream is closed
^CTraceback (most recent call last):
File "test.py", line 5, in <module>
tornado.ioloop.IOLoop.instance().start()
File "/usr/local/lib/python2.6/dist-packages/tornado/ioloop.py", line 282, in start
event_pairs = self._impl.poll(poll_timeout)
KeyboardInterrupt
The problem is limited solely to the TornadoWebSocketClient class. Both of the other clients work with the server and SSL enabled. I think the problem is due to not using a tornado.iostream.SSLIOStream object in place of a tornado.iostream.IOStream object. I'll try and confirm my suspicions and post a fix if I can.
The latest Firefox and the latest Google Chrome set the value of the "Sec-WebSocket-Version" header to 8 and 13, respectively. I can set the version that CherryPy expects with the "tools.websocket.version" config option, but this setting is used in a basic equality check (https://github.com/Lawouach/WebSocket-for-Python/blob/master/ws4py/server/cherrypyserver.py#L133). So currently I can deploy a site which is compatible with the latest Firefox or the latest Chrome, but not both.
I propose that "tools.websocket.version" accept either a number or a range. So I could say either
tools.websocket.version = 8
or
tools.websocket.version = 8-13
I will submit a patch via a Github pull request sometime this week which adds this functionality.
Following Armin's comment, I'm tempted to drop anything but 2.7 and 3.3.2. Mostly, it would simplify tremendously the string/bytes handling across the board as we could use unicode/bytes litterals. I'd be surprised if it wouldn't improve performances a little as well.
It would happen after 0.3.0 release, so that people still using other versions can benefit from the latest fixes.
Find the best approach to port to py3k, probably at a compat module like CherryPy uses.
I'm trying to execute any example code and everytime the socket is created, python throws an exception like this:
127.0.0.1 - - [11/Mar/2012:11:10:45] "GET /js/jquery-1.6.2.min.js HTTP/1.1" 304 - "http://localhost:9000/" "Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.11 (KHTML, like Gecko) Ubuntu/11.10 Chromium/17.0.963.78 Chrome/17.0.963.78 Safari/535.11"
[11/Mar/2012:11:10:45] Handler created: <__main__.ChatWebSocketHandler object at 0x94d402c>
127.0.0.1 - - [11/Mar/2012:11:10:45] "GET /ws HTTP/1.1" 101 - "" ""
[11/Mar/2012:11:10:45] Managing WebSocket connection from 127.0.0.1:54256
[11/Mar/2012:11:10:46] Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/ws4py/server/cherrypyserver.py", line 339, in broadcast
ws_handler.send(message, message.is_binary)
File "/usr/local/lib/python2.7/dist-packages/ws4py/websocket.py", line 172, in send
self.sender(payload.single(mask=self.stream.always_mask))
File "/usr/lib/python2.7/socket.py", line 224, in meth
return getattr(self._sock,name)(*args)
File "/usr/lib/python2.7/socket.py", line 170, in _dummy
raise error(EBADF, 'Bad file descriptor')
error: [Errno 9] Bad file descriptor
I'm not really sure what I'm doing wrong, but using another ws4py version doesn't seem to solve it...
Steps to reproduce(?):
Result:
The websocket appears to have some wsgi
variables set. Is it correct that websocket.path == environ.PATH_INFO
?
Is that the only wsgi environ
set on the websocket? Checking the websocket for CONTENT_TYPE, HTTP_USER_AGENT
, variables set on wsgi environment
, shows they aren't set on the websocket.
Strangely enough, HTTP_COOKIE
isn't set on the wsgi environment
available on the wsgi app handler
if the client is a Javascript websocket client on the Chrome browser. I haven't tested a python client (or other browser clients) to check whether Chrome is transmitting host cookies on the websocket connection.
I'm attempting to use client cookies to authenticate the websocket connection instead of performing additional explicit websocket authentication on the first websocket message.
Any thoughts?
When the websocket closes, there is a code and a reason. I can subclass it and override closed() to get these. But I cannot get them if I am handed a stock websocket object, for example when I use WSGI server (with gevent). Therefore, could you please store the code and reason in the websocket? For example,
ws4py/client/init.py line 106
def close(self, reason='', code=1000):
if not self.client_terminated:
self.client_terminated = True
self.close_code = code ### added ###
self.close_reason = reason ### added ###
self.write_to_connection(self.stream.close(code=code, reason=reason).single(mask=True))
had this on python 3.2
File: ws4py/client/tornadoclient.py
line 40: b"\r\n\r\n" in stead of "\r\n\r\n"
line 45: b'\r\n' instead of '\r\n'
I receive this error:
Traceback (most recent call last):
File "venv/lib/python2.6/site-packages/ws4py/client/threadedclient.py", line 93, in _receive
next_size = s.parser.send(bytes)
File "venv/lib/python2.6/site-packages/ws4py/streaming.py", line 181, in receiver
is_valid, _, _, _ = utf8validator.validate(bytes)
File "venv/lib/python2.6/site-packages/ws4py/utf8validator.py", line 108, in validate
self.state = Utf8Validator.UTF8VALIDATOR_DFA[256 + (self.state << 4) + Utf8Validator.UTF8VALIDATOR_DFA[ba[i]]]
TypeError: list indices must be integers, not str
When a WebSocket is created using an underlying IPv6 socket, its local_address (and, I assume, the peer address) returns a 4-tuple instead of a 2-tuple.
This means that automatic unpacking of the address into hostname, port throws a ValueError.
Minimal example (using the cherrypy tools)
import cherrypy
from ws4py.server.cherrypyserver import WebSocketPlugin, WebSocketTool
from ws4py.websocket import EchoWebSocket
cherrypy.config.update({'server.socket_port': 9000})
cherrypy.config.update({'server.socket_host': "::1"})
WebSocketPlugin(cherrypy.engine).subscribe()
cherrypy.tools.websocket = WebSocketTool()
class Root(object):
@cherrypy.expose
def index(self):
return """<script type="text/javascript">
var sock = new WebSocket("ws://localhost:9000/ws");</script>"""
@cherrypy.expose
def ws(self):
pass
cherrypy.quickstart(Root(), '/', config={'/ws': {'tools.websocket.on': True,
'tools.websocket.handler_cls': EchoWebSocket}})
This throws a ValueError when navigating to localhost:9000
The obvious workaround is not using IPv6 addresses in the server deployment.
A fix would be to have WebSocket.local_address and WebSocket.peer_address return the first two elements of the underlying socket's name.
client/init.py has:
self.__buffer = body
It looks like self.__buffer is never used, which means that if any bytes (e.g., the first data packet) are received along with the headers, those bytes will be ignored and the connection will probably get into a bad state.
Adding this after handshake_ok() fixes things in this case:
if body != '':
process(body)
Does that seem like a reasonable fix?
i have realized wss server using ws4py and cherrypy for python 2.6 but it looks very strange
I understand ssl.SSLSocket send\recv works only with string not bytearray and
for sending string 'abcd' it must looks like '\x82\x06abcd\r'
it''ll be cool to have ability to work with bytearray by wss
The change in #83 changes SelectPoller.poll() to return an empty list, but it makes a busy loop that uses a lot of CPU as it continually loops over new empty arrays.
It is imported in:
I know, itβs not part of the official spec, but you can run websockets over local unix sockets just fine.
The node.js ws
module supports servers and clients that bind to local unix sockets. I have a node.js server which acts as WS server and I want to consume it via python.
I'm just starting to use your lib, but so far it's been quite useful, thanks a lot :-)
I just spotted what I think is an error at https://github.com/Lawouach/WebSocket-for-Python/blob/master/example/echo_client.py#L5
def opened(self, protocols, extensions):
Should be instead:
def opened(self):
The server has a memory leak. I found it because my server ran out of memory after several thousand clients connected and disconnected. I verified the leak using Python objgraph pypi.python.org/pypi/objgraph . It appears that for every websocket connection, two generators, one Stream, and one Frame are leaked. Even after the connection is closed, these objects remain in memory. Even after garbage collection. To verify it, add the following two lines to the sample echo server.
for x in ['generator', 'Stream', 'Frame', 'TextMessage']:
print x, len(objgraph.by_type(x))
Now connect and disconnect several clients. You will see the number of instances of these objects climb, even after all clients are disconnected, even after garbage collection.
I use geventserver. I have not tried with the other servers. But there is no leakage of Greenlets, so I suspect the issue is not related to gevent.
Happily installed ws4py and all the other goodies and was thrilled to launch 'echo_cherrypy_server.py' and see it working flawlessly in Chrome. However, seems other python programs in examples directory are not working at all. For instance...
$ python autobahn_test_servers.py
python echo_client.py
Traceback (most recent call last):
File "echo_client.py", line 27, in
ws.connect()
File "/Library/Python/2.7/site-packages/ws4py/client/init.py", line 58, in connect
self.process_response_line(response_line)
File "/Library/Python/2.7/site-packages/ws4py/client/init.py", line 102, in process_response_line
raise HandshakeError("Invalid response status: %s %s" % (code, status))
ws4py.exc.HandshakeError: Invalid response status: 404 Not Found
I'm running OSX Lion 10.7.3, Python 2.7.1 (r271:86832, Jun 16 2011, 16:59:05)
[GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)] on darwin
The file ws4py/server/cherrypyserver.py contains a few tabs that should be replaced by 8 spaces each.
Working with python3.2, a closed socket is not properly removed from the 'pool' (?) of sockets to send a message through.
When the browser is closing its connection the server receives it, processes it (cleans all up, making the WebSocket members all None types), but somehow it stays there. Resulting in a persisting attribute error :
'NoneType' object has no attribute 'text_message'
>>> urlsplit('ws://localhost:8080/some-path')
SplitResult(scheme='ws', netloc='', path='//localhost:8080/some-path', query='', fragment='')
This results in 'host' being None, and an obtuse 'Connection Refused' message passed to close(), but without enough information to debug.
I see that 'websocket-client' has it's own _parse_url method that works around this bug:
https://github.com/liris/websocket-client/blob/master/websocket.py#L105
I'll try and work up a patch, if a solution like the above is reasonable?
Thanks
I tried to implement a simple WebSocket client for a CherryPy server which should work like the droid_sensor.py and its server under "example", but if I try to run the client it always stops randomly in the send loop and exits with a random WebSocket error code (one of 1002, 1006 and 1007).
This is the server log from the CherryPy server:
127.0.0.1 - - [18/Feb/2013:02:49:54] "GET /ws HTTP/1.1" 101 - "" ""
[18/Feb/2013:02:49:54] Managing WebSocket connection from 127.0.0.1:55280
[18/Feb/2013:02:49:54] Managing WebSocket connection from 127.0.0.1:55280
Exception in thread WebSocket client at 127.0.0.1:55280:
Traceback (most recent call last):
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 552, in __bootstrap_inner
self.run()
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 505, in run
self.__target(*self.__args, **self.__kwargs)
File "/Users/martin/Desktop/test/ENV/lib/python2.7/site-packages/ws4py/websocket.py", line 246, in run
self._cleanup()
File "/Users/martin/Desktop/test/ENV/lib/python2.7/site-packages/ws4py/websocket.py", line 197, in _cleanup
self.stream._cleanup()
AttributeError: 'NoneType' object has no attribute '_cleanup'
[18/Feb/2013:02:49:55] Removing WebSocket connection 127.0.0.1:55280
[18/Feb/2013:02:49:55] Removing WebSocket connection 127.0.0.1:55280
This is my client (very similar to example/droid_sensor.py):
https://gist.github.com/muellermartin/4974648
and this is the server:
https://gist.github.com/muellermartin/4974657
P.S.: The host in line https://github.com/Lawouach/WebSocket-for-Python/blob/master/example/droid_sensor.py#L98 seems to be wrong (script crashes with ValueError: Invalid scheme: http
) - shouldn't this be "ws://127.0.0.1:9000/ws"?
I tring to use bottlepy with ws4py in python 3.3 like this:
# ws4py -> wsapp
from ws4py.server.wsgiutils import WebSocketWSGIApplication
from ws4py.websocket import EchoWebSocket
wsapp = WebSocketWSGIApplication(handler_cls = EchoWebSocket)
# Bottlepy -> app
from bottle import Bottle, run
app = Bottle(catchall = True)
# mount wsapp on app (use bottle API)
app.mount('/ws', wsapp) # mount websocket at "/127.0.0.1:8080/ws"
run(app = app, host = '127.0.0.1', port = '8080',
debug = True, quiet = False)
And I test WebSocket Function with WebSocket Echo Page (using ws://127.0.0.1:8080/ws
as location), browser is firefox 20.0 .
But I got some error:
('Sec-WebSocket-Accept', base64.b64encode(sha1(key + WS_KEY).digest())),
TypeError: Can't convert 'bytes' object to str implicitly
I try to use bytes(key, 'utf8')
to workaround (not sure it really ok or not...), but another error appear...
self.make_websocket(environ['ws4py.socket'],
KeyError: 'ws4py.socket'
Please give me a hand... thanks!
File "build/bdist.linux-i686/egg/ws4py/websocket.py", line 232, in run
bytes = sock.recv(self.reading_buffer_size)
error: [Errno 110] Connection timed out
i think can except this exception then call closed func like this:
try:
self.opened()
sock = self.sock
fileno = sock.fileno()
process = self.process
while not self.terminated:
bytes = sock.recv(self.reading_buffer_size)
if not process(bytes):
break
except:
self.closed(110, "Connection timed out")
finally:
self.client_terminated = self.server_terminated = True
try:
if not s.closing:
self.closed(1006, "Going away")
else:
self.closed(s.closing.code, s.closing.reason)
finally:
s = sock = fileno = process = None
self.close_connection()
self._cleanup()
This crashes after consuming all system memory within seconds.
while True:
streaming.Stream()
Apple devices do not work with ws4py, they produce HandshakeError: WebSocket version required
error. They only work with allow_draft76
with Tornado, but I would like to use cherrypy. Is this a limitation in ws4py or cherrypy? Is there a reason not to enable these devices? If no, is there a simple solution or a workaround to use them?
I'm using ws4py to build a simple command-line WS client. However, once it gets going, there's no way to bring it down without kill
ing it. I see that WebSocketClient
is using the threading
package; how can I get it to close the connection on KeyboardInterrupt
(or something similar)?
The code (set WEBSOCKET_SERVER_URL to a real WS server):
from ws4py.client.threadedclient import WebSocketClient
WEBSOCKET_SERVER_URL = "INSERT_VALID_URL_HERE"
class CantInterruptClient(WebSocketClient):
def opened(self):
print "Opened."
def closed(self, code):
print "Closed."
try:
print "Creating client..."
cant_interrupt_client = CantInterruptClient(WEBSOCKET_SERVER_URL)
cant_interrupt_client.connect()
except KeyboardInterrupt:
print "Attempting to quit..."
cant_interrupt_client.close()
Typical command line output:
$ python ws4py-interrupt.py
Creating client...
Opened.
^C^C^C^C^C^C^C^C
How do I specify what sub-protocols my application supports? I see that the WebSocketTool upgrade method takes a protocols named parameter but how do I specify that list from my application.
Also, I've noticed a spec compliance issue in the upgrade method (e.g. server/cherrypyserver.py about line 158):
if s in protocols:
ws_protocols.append(s)
and then later:
if ws_protocols:
response.headers['Sec-WebSocket-Protocol'] = ', '.join(ws_protocols)
While a client is allowed to specify multiple comma separated sub-protocols in the handshake request, the handshake response must only contain one of those items that the server has selected. See the /subprotocol/ description in the server handshake section: http://tools.ietf.org/html/rfc6455#section-4.2.2
When launching the 'echo_cherrypy_server.py' example, the CherryPy server starts, but the client connection fails with a TypeError.
To reproduce:
[31/Oct/2012:10:40:14] HTTP
Request Headers:
PRAGMA: no-cache
UPGRADE: websocket
HOST: 127.0.0.1:9000
ORIGIN: http://localhost:9000
CONNECTION: keep-alive, Upgrade
CACHE-CONTROL: no-cache
SEC-WEBSOCKET-VERSION: 13
ACCEPT: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
USER-AGENT: Mozilla/5.0 (Windows NT 6.1; rv:16.0) Gecko/20100101 Firefox/16.0
ACCEPT-LANGUAGE: fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3
SEC-WEBSOCKET-KEY: 6mxn50NE+8xKZ15w2/NQRw==
Remote-Addr: 127.0.0.1
ACCEPT-ENCODING: gzip, deflate
[31/Oct/2012:10:40:14] HTTP Traceback (most recent call last):
File "C:\python32\lib\site-packages\cherrypy-3.2.2-py3.2.egg\cherrypy_cprequest.py", line 647, in respond
self.hooks.run('before_request_body')
File "C:\python32\lib\site-packages\cherrypy-3.2.2-py3.2.egg\cherrypy_cprequest.py", line 112, in run
raise exc
File "C:\python32\lib\site-packages\cherrypy-3.2.2-py3.2.egg\cherrypy_cprequest.py", line 102, in run
hook()
File "C:\python32\lib\site-packages\cherrypy-3.2.2-py3.2.egg\cherrypy_cprequest.py", line 62, in call
return self.callback(**self.kwargs)
File "C:\python32\lib\site-packages\ws4py-0.2.3-py3.2.egg\ws4py\server\cherrypyserver.py", line 149, in upgrade
ws_key = base64.b64decode(key)
File "C:\python32\lib\base64.py", line 83, in b64decode
raise TypeError("expected bytes, not %s" % s.class.name)
TypeError: expected bytes, not str
127.0.0.1 - - [31/Oct/2012:10:40:14] "GET /ws HTTP/1.1" 500 1686 "" "Mozilla/5.0 (Windows NT 6.1; rv:16.0) Gecko/20100101 Firefox/16.0"
[1] Windows 7, Python 3.2.3, CherryPy 3.2.2.
diff --git a/example/echo_client.py b/example/echo_client.py
index 94b1f04..9b6698e 100644
--- a/example/echo_client.py
+++ b/example/echo_client.py
@@ -13,7 +13,7 @@ class EchoClient(WebSocketClient):
print i
self.send("*" * i)
- def closed(self, code, reason):
+ def closed(self, code, reason=None):
print "Closed down", code, reason
def received_message(self, m):
diff --git a/ws4py/exc.py b/ws4py/exc.py
index 5a87f36..5a22ee2 100644
--- a/ws4py/exc.py
+++ b/ws4py/exc.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
__all__ = ['WebSocketException', 'FrameTooLargeException', 'ProtocolException',
- 'FUnsupportedFrameTypeException', 'TextFrameEncodingException',
+ 'UnsupportedFrameTypeException', 'TextFrameEncodingException',
'StreamClosed', 'HandshakeError', 'InvalidBytesError']
class WebSocketException(Exception): pass
diff --git a/ws4py/websocket.py b/ws4py/websocket.py
index bbff576..cf78b8a 100644
--- a/ws4py/websocket.py
+++ b/ws4py/websocket.py
@@ -135,7 +135,7 @@ class WebSocket(object):
bytes = payload.next()
first = True
for chunk in payload:
- write(message_sender(bytes).fragment(first=first))
+ self.sender(message_sender(bytes).fragment(first=first))
bytes = chunk
first = False
Is there a way to send messages to individual clients using client IDs? It would be awesome if you could include that in the chat example or let me know if you plan to implement it. This would be useful, for example, in a chat server that supports private messages.
If you use a line like ws = EchoClient('wss://myserver.org:443')
you get an invalid GET request:
0000 47 45 54 20 20 48 54 54 50 2f 31 2e 31 0d 0a 48 GET HTTP/1.1..H
Note the lack of a /
there between the GET
and HTTP/1.1
.
Using ws = EchoClient('wss://myserver.org:443/')
works as expected.
Lack of a trailing slash when requesting a site's root really ought to be handled properly.
This appears to have been in place for some time. I only picked it up in the process of preparing a version bump, to 0.2.4, requested by another, gentoo
platform linux2 -- Python 3.2.3 -- pytest-2.2.4
collected 22 items
test/test_cherrypy.py F
test/test_frame.py ............
test/test_stream.py .........
=================================== FAILURES ===================================
___________________________ CherryPyTest.test_plugin ___________________________
self = <test.test_cherrypy.CherryPyTest testMethod=test_plugin>
def test_plugin(self):
self.assertEquals(len(cherrypy.engine.websocket.pool), 0)
s = FakeSocket()
h = EchoWebSocket(s, [], [])
cherrypy.engine.publish('handle-websocket', h, ('127.0.0.1', 0))
self.assertEquals(len(cherrypy.engine.websocket.pool), 1)
k = cherrypy.engine.websocket.pool.keys()[0]
E TypeError: 'dict_keys' object does not support indexing
test/test_cherrypy.py:68: TypeError
===================== 1 failed, 21 passed in 0.67 seconds ======================
You can tell me if this is coming from ws4py here of from cherrypy itself. Holds true for
cherrypy-3.2.0 - 3.2.2
The constructor of TornadoWebSocketClient
calls the constructor of WebSocketBaseClient
with version=...
, but WebSocketBaseClient.__init__
only supports extensions
as an extra arg, and not version
.
https://github.com/Lawouach/WebSocket-for-Python/blob/master/ws4py/client/tornadoclient.py#L14
https://github.com/Lawouach/WebSocket-for-Python/blob/master/ws4py/client/\_\_init\_\_.py#L18
The latest version of chrome has started to fail for me with a message about the server sending a masked message. I found this commit: 19cfdb1 which seems seems to be addressing the issue.
If I install version 0.1.3 my websockets communication works again.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.