Я использую Python для реализации простого websocket сервера. Квитирование, которое я использую, прибывает из http://en.wikipedia.org/w/index.php?title=WebSockets&oldid=372387414.
Само квитирование, кажется, работает, но когда я совершил нападки, отправляют, я получаю ошибку JavaScript:
Непойманная ошибка: INVALID_STATE_ERR: исключение DOM 11
Вот HTML:
ws_json
И вот код Python:
import socket
import threading
import json
PORT = 8888
LOCATION = "localhost:8888"
def handler(s):
print " in handler "
ip, _ = s.getpeername()
print "New connection from %s" % ip
request = s.recv(1024)
print "\n%s\n" % request
print s.getpeername()
# send response
response = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n"
response += "Upgrade: WebSocket\r\n"
response += "Connection: Upgrade\r\n"
try:
peername = s.getpeername()
response += "Sec-WebSocket-Origin: http://%s\r\n" % peername[0] # % request[request.index("Origin: ")+8:-4]
except ValueError:
print "Bad Request"
raise socket.error
response += "Sec-WebSocket-Location: ws://%s\r\n" % LOCATION
response += "Sec-WebSocket-Protocol: sample"
response = response.strip() + "\r\n\r\n"
print response
s.send(response)
while True:
length = s.recv(1)
print length
if not length:
break
length = int(length)
print "Length: %i" % length
data = s.recv(length)
print "Received: %s" % data
print ""
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('localhost', PORT))
s.listen(5)
print "server is running..."
while True:
sock, addr = s.accept()
threading.Thread(target=handler, args=(sock, )).start()
Кто-либо знает то, что я делаю неправильно здесь?
Я тестировал ваш код в Firefox 4 и получил ту же ошибку при нажатии кнопки отправки, однако до этого я получил
Firefox не может установить соединение на сервер по адресу ws: // localhost: 8888 /.
, вероятно, поэтому объект WebSocket был уничтожен. Я подозреваю, что в вашем ответе на рукопожатие чего-то не хватает, поэтому Firefox закрывает сокет.
Из статьи в Википедии о веб-сокетах:
Sec-WebSocket-Key1 и Sec-WebSocket-Key2 и поля восемь байтов после полей случайные токены, которые сервер использует для построить 16-байтовый токен в конце рукопожатия, чтобы доказать, что он прочтите рукопожатие клиента.
Ответ вашего сервера не имеет этого специального номера внизу, поэтому я думаю, нам нужно выяснить, как его сгенерировать, и включить его.
РЕДАКТИРОВАТЬ: Как сгенерировать это число
Давайте начнем с key1, key2 и 8 байтов в конце рукопожатия
key1 = "18x 6]8vM;54 *(5: { U1]8 z [ 8"
key2 = "1_ tx7X d < nw 334J702) 7]o}` 0"
end8 = "Tm[K T2u"
Мы создаем число для каждого ключа, игнорируя каждый символ, который не является цифрой 0 -9. В Python:
def numFromKey(key):
return int(filter(lambda c: c in map(str,range(10)),key))
затем мы делим это число на количество пробелов в исходной строке ключа, так что вот функция, которая подсчитывает пробелы в строке.
def spacesIn(key):
return len(filter(lambda c: c==' ',key))
Два числа, полученные из ключей:
pkey1 = numFromKey(key1)/spacesIn(key1)
pkey2 = numFromKey(key2)/spacesIn(key2)
Теперь нам нужно объединить байты pkey1, pkey2 и end8. Обработанные ключи должны быть представлены как 32-битные числа с прямым порядком байтов.
from struct import pack
catstring = pack('>L',pkey1) + pack('>L',pkey2) + end8
Затем мы берем хэш md5 этих байтов, чтобы получить магическое число, которое мы прикрепляем к концу рукопожатия.
import md5
magic = md5.new(catstring).digest()
Вот как я думаю, это работает по крайней мере