Сокет питон сервер + клиент js

Автор Сообщение
20 Фев, 2016 13:58
Здравствуйте, мне нужно реализовать сокет на python который будет слушать бесперибойник через com порт на windows, а клиент в браузере будет слушать его при помощи js выводить, но у меня возникла проблема при обновлении страницы сокет падает, это может произойти не сразу но в конце концов он падает и приходится перезапустить скрипт python что бы возобновить работу сокета. Сначала я выложу свою реализацию которая работает как я описал выше, а потом выложу код который представляет собой чат и работает в нескольких режимах в зависимости от параметров командной строки, и сокету который реализован на этом годе я хочу каким либо образом передавать данные с бесперибойника и которые будут выводиться в клиенте браузера. Ну начнем моя реализация.
############### код сервера сокета
import serial
import sys
sys.path.append('../..')

import time
from SingleSocket.Output import Output

SOCKET_PORT = 9999
SOCKET_HOST = '127.0.0.1'
stream = Output(host=SOCKET_HOST,
port=SOCKET_PORT,
web=True)
def starts():

port = stream.start()

print('Emitting port: {:d}'.format(port))

if not stream.running:
exit(0)
ser = serial.Serial('COM4', 2400, timeout=0)
while ser:
try:

ser.write(b"Q1\r")
ups1= ser.read(100)
ser.timeout = 1
#ser.open()
print(ups1)
stream.append_msg(ups1)
#time.sleep(2)
except socket.error, msg:
stream.stop()
ser.close()
ser.open()
starts()
starts()

####################### библиотека
#!usr/bin/env python
"""Output socket for limited and unlimited concurrent clients.

Usage:
```
# Starts
stream = Output(host='localhost', port=9999, web=False)
stream.start()

# Checks that port is available
if stream.running:

# Sends a message
stream.send('Hello peer!!')

# Stops
stream.stop()
```
"""

from Queue import Queue
import socket
import base64
import threading
from hashlib import sha1


class Output(object):
"""
SingleSocket output class.
"""

MAGIC = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
HANDSHAKE_HEAD = "HTTP/1.1 101 Switching Protocols\r\n" \
"Upgrade: websocket\r\n" \
"Connection: Upgrade\r\n" \
"Sec-WebSocket-Accept: {hash}\r\n" \
"\r\n"

def __init__(self, host, port, web=False, max_clients=None, password=None,
welcome=''):
"""
Constructor

:param host: str. Host connected from. Set to '0.0.0.0' to allow all.
:param port: int. Port connected to.
:param web: bool. Flag for a websocket connection.
:param max_clients: bool. 0 or None for unlimited.
:param password: str. If set is used for logging in clients.
:param welcome: str. Message sent when a client is connected.
:return: void
"""
self._max_clients = max_clients
self._new_clients = Queue()
self._clients = Queue()

self._password = password

self._released = threading.Event()
self._running = threading.Event()

self._host = host
self._port = port

self._web = web

#if not welcome:
# welcome = 'You are logged in'

self._welcome = '{!s}{!s}'.format(welcome, '\n')

self._server = None
self._messages = Queue()

self._emitter = None
self._runtime = None

pass

def reconfigure(self, host, port, web):
"""
Recycles the object. Stopping the object before is recommended.

:param host: str
:param port: int
:param web: bool
:return: void
"""
print "[*] Recycled object"

return self.__init__(host=host, port=port, web=web)

def stop(self):
"""
Nice stop

:return: void
"""
try:
self._server.shutdown(socket.SHUT_RDWR)
self._server.close()

except socket.error:
print "[!] Closing when server is not running"

self._kill_emitter()

self._runtime.join()

print "[*] Stopped communication"

def start(self, timeout=60):
"""
Starts communication threads and returns the used port. Waits until the
appropriate thread sets the connected event. After the set timeout
seconds, if client is not connected, continues.

:param timeout: int.
:return: void
"""
self._runtime = threading.Thread(target=self._listen)

self._runtime.start()

self._released.wait(timeout)

return self._port

def append_msg(self, message):
"""
Puts a message into the messages queue to be sent immediately.

:param message: str
:return: bool
"""

if self._web and len(message) > 125:

self._messages.put(message[:125])
return self.append_msg(message[125:])

self._messages.put(message)

pass

@property
def running(self):
"""
Returns True if socket is working. Main flag to know the status.

:return: bool
"""
return self._running.is_set()

def _listen(self):
"""
Starts listening asynchronously

:return: void
"""

if not self._start_server():

print "[x] Port in use: {:d}".format(self._port)

self._released.set()

return

while self._running:
try:
client, address = self._server.accept()

print "[*] Accepted from: {!s}:{:d}".format(address[0],
address[1])

except socket.error:
print '[x] Socket error accepting'

self._running.clear()

return

if self._reaches_max_clients():
self._clients.get()

self._released.set()

self._new_clients.put(client)

self._emitter = threading.Thread(target=self._talk)
self._emitter.start()

return

def _reaches_max_clients(self):
"""
Checks if connection reaches the max clients limit.
If max clients is 0 or unset, clients number is unlimited.

:return: bool
"""
result = self._max_clients \
and self._clients.qsize() >= self._max_clients

return result

def _start_server(self):
"""
Starts server on first available port. Returns True if does.
If there is no port available returns False.

:return: bool
"""
self._server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self._server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

try:
self._server.bind((self._host, self._port))

except socket.error:
return False

self._running.set()

self._server.listen(1)

print '[*] Listening on {!s}:{:d}'.format(self._host, self._port)

return True

def _kill_emitter(self):
"""
Given the threat for client handling, nicely closes the thread and
the client types.

:return: void
"""
if self._released.is_set():
self._released.clear()
self._emitter.join()

print '[*] Emitter killed'

else:
print '[!] No emitter to kill'

pass

def _handshake(self, headers, client):
"""
Given the headers and the types resource, does a handshake only on
websocket communication.

:param headers: dict
:return: void
"""
for key, value in headers.iteritems():
print key, ':', value

socket_key = headers['Sec-WebSocket-Key']

magic = self._hash_magic(socket_key=socket_key)

response = self.HANDSHAKE_HEAD.format(hash=magic)

client.send(response)

print "[*] Handshake response:\n\t{!s}".format(response)

@classmethod
def _format_web_msg(cls, msg):
"""
Given a message returns the content formatted to send it using websocket
protocol.

:param msg: str
:return: str
"""
message = bytearray([0b10000001, len(msg)])

# append the data bytes
for byte in bytearray(msg):
message.append(byte)

return message

def _send(self, msg, clients=list()):
"""
Given a message sends to all connected clients.

If clients parameter is set sends the message to the list of clients
contained by.

Else if clients is not set or is empty, sends the message to the context
logged in clients.

:param msg: mixed
:param clients: list
:return: void
"""
if self._web:
msg = self._format_web_msg(msg=msg)

if not clients:
clients = list(self._clients.queue)

while len(clients):
client = clients.pop(0)
client.send(msg)

return

def _login_all(self):
"""
In case of normal socket receives the client key pass.

In case of websocket receives the data for handshake, does the
appropriate handshake and after receives the key pass.

Accepts only valid new clients moving them to logged in clients.
Only logged in clients receive the output messages.

:return: void
"""
if self._new_clients.empty():
return

client = self._new_clients.get()

if self._web:

data = self._receive_hello(client=client, handshake=True)

print "[*] Websocket protocol is enabled"

headers = self._parse_headers(data)

self._handshake(headers=headers, client=client)

data = self._receive_hello(client=client, handshake=False)

if self._login(data):
self._send(self._welcome, [client])
self._clients.put(client)

else:
self._send('Authorized only\n', [client])
client.close()

self._login_all()

def _receive_hello(self, client, handshake=False):
"""
Given a socket client waits for receiving data from client.
If context password is set waits and returns the received data.
If handshake parameter is True waits and returns the received data.
If any of above conditions happens does not wait and returns None

:param client: resource socket client
:param handshake: bool
:return: str|None
"""
if not self._password and not handshake:
return None

hello = client.recv(1024)

print "[*] Received: " + hello

return hello

def _login(self, key_pass):
"""
Given a key pass returns True if matches with the context password.
Returns False if does not match.

:param key_pass: str
:return: bool
"""
if not self._password:
return True

elif self._password == key_pass.strip():
return True

else:
return False

def _talk(self):
"""
- Receives the input from the new client.
- Log in the new clients.
- Maintains the communication meanwhile the connection with the client
is alive.

:return: void
"""

self._login_all()

while self._released.is_set():

self._send_all()

self._close_all()

def _close_all(self):
"""
Closes all clients and dequeues clients container
:return: void
"""
if self._clients.empty():
return

client = self._clients.get()
#self._send('Connection closed\n', [client])
client.close()

self._close_all()

def _send_all(self):
"""
Prepares and sends all message in queue.

:return: void
"""
if self._messages.empty():
return

message = self._messages.get()

try:
self._send(message)

print "[*] Message sent:\n\t{!s}".format(message)

except socket.error, exc:

print("[x] Error sending to a client. {!s}".format(exc.message))

self._send_all()

@classmethod
def _hash_magic(cls, socket_key):
"""
Given the types key returns a new hash composed by the key
and the magic uuid.

:param socket_key: str
:return: str
"""
output = sha1(socket_key + cls.MAGIC).digest()
output = base64.b64encode(output)

return output

@classmethod
def _parse_headers(cls, data):
"""
Parses headers from client

:param data: str
:return: dict
"""
headers = {}
lines = data.splitlines()

for l in lines:
parts = l.split(": ", 1)

if len(parts) == 2:
headers[parts[0]] = parts[1]

headers['get'] = lines[0]

headers['code'] = lines[len(lines) - 1]

return headers


//// js код

это был первый случай как я реализовал, но сокет падает вот второй случай

############# сокет сервер ########################

'''
The MIT License (MIT)
Copyright (c) 2013 Dave P.
'''

import signal, sys, ssl
from SimpleWebSocketServer import WebSocket, SimpleWebSocketServer, SimpleSSLWebSocketServer
from optparse import OptionParser
import serial
import sys
sys.path.append('../..')
#ser = serial.Serial('COM4', 2400, timeout=0)
class SimpleEcho(WebSocket):

def handleMessage(self):
#ser.write(b"Q1\r")
#self.data= ser.read(100)
self.sendMessage(self.data)


def handleConnected(self):
pass

def handleClose(self):
pass

clients = []
class SimpleChat(WebSocket):
def handleMessage(self):
for client in clients:
if client != self:

client.sendMessage(self.address[0] + u' - ' + self.data)

def handleConnected(self):
print (self.address, 'now')
for client in clients:
client.sendMessage(self.address[0] + u' - now')
self.ser.write(b"Q1\r")
self.data= ser.read(100)
self.ser.timeout = 1
print self.data
print 'hello'
client.sendMessage(self.data)
clients.append(self)

def handleClose(self):
clients.remove(self)
print (self.address, 'closed')
for client in clients:
client.sendMessage(self.address[0] + u' - now')


if __name__ == "__main__":

parser = OptionParser(usage="usage: %prog [options]", version="%prog 1.0")
parser.add_option("--host", default='', type='string', action="store", dest="host", help="hostname (localhost)")
parser.add_option("--port", default=8000, type='int', action="store", dest="port", help="port (8000)")
parser.add_option("--example", default='echo', type='string', action="store", dest="example", help="echo, chat")
parser.add_option("--ssl", default=0, type='int', action="store", dest="ssl", help="ssl (1: on, 0: off (default))")
parser.add_option("--cert", default='./cert.pem', type='string', action="store", dest="cert", help="cert (./cert.pem)")
parser.add_option("--ver", default=ssl.PROTOCOL_TLSv1, type=int, action="store", dest="ver", help="ssl version")

(options, args) = parser.parse_args()

cls = SimpleEcho
if options.example == 'chat':
cls = SimpleChat

if options.ssl == 1:
server = SimpleSSLWebSocketServer(options.host, options.port, cls, options.cert, options.cert, version=options.ver)
else:
server = SimpleWebSocketServer(options.host, options.port, cls)

def close_sig_handler(signal, frame):
server.close()
sys.exit()

signal.signal(signal.SIGINT, close_sig_handler)

server.serveforever()


################ бибилиотека ############################
'''
The MIT License (MIT)
Copyright (c) 2013 Dave P.
'''
import sys
VER = sys.version_info[0]
if VER >= 3:
import socketserver
from http.server import BaseHTTPRequestHandler
from io import StringIO, BytesIO
else:
import SocketServer
from BaseHTTPServer import BaseHTTPRequestHandler
from StringIO import StringIO

import hashlib
import base64
import socket
import struct
import ssl
import errno
import codecs
from collections import deque
from select import select

import serial
import sys
sys.path.append('../..')

#__all__ = ['WebSocket',
# 'SimpleWebSocketServer',
# 'SimpleSSLWebSocketServer']

def _check_unicode(val):
if VER >= 3:
return isinstance(val, str)
else:
return isinstance(val, unicode)

class HTTPRequest(BaseHTTPRequestHandler):
def __init__(self, request_text):
if VER >= 3:
self.rfile = BytesIO(request_text)
else:
self.rfile = StringIO(request_text)
self.raw_requestline = self.rfile.readline()
self.error_code = self.error_message = None
self.parse_request()

_VALID_STATUS_CODES = [1000, 1001, 1002, 1003, 1007, 1008,
1009, 1010, 1011, 3000, 3999, 4000, 4999]

HANDSHAKE_STR = (
"HTTP/1.1 101 Switching Protocols\r\n"
"Upgrade: WebSocket\r\n"
"Connection: Upgrade\r\n"
"Sec-WebSocket-Accept: %(acceptstr)s\r\n\r\n"
)

GUID_STR = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'

STREAM = 0x0
TEXT = 0x1
BINARY = 0x2
CLOSE = 0x8
PING = 0x9
PONG = 0xA

HEADERB1 = 1
HEADERB2 = 3
LENGTHSHORT = 4
LENGTHLONG = 5
MASK = 6
PAYLOAD = 7

MAXHEADER = 65536
MAXPAYLOAD = 33554432

class WebSocket(object):

def __init__(self, server, sock, address):
self.server = server
self.client = sock
self.address = address

self.handshaked = False
self.headerbuffer = bytearray()
self.headertoread = 2048

self.fin = 0
self.data = bytearray()
self.opcode = 0
self.hasmask = 0
self.maskarray = None
self.length = 0
self.lengtharray = None
self.index = 0
self.request = None
self.usingssl = False

self.frag_start = False
self.frag_type = BINARY
self.frag_buffer = None
self.frag_decoder = codecs.getincrementaldecoder('utf-8')(errors='strict')
self.closed = False
self.sendq = deque()

self.state = HEADERB1

# restrict the size of header and payload for security reasons
self.maxheader = MAXHEADER
self.maxpayload = MAXPAYLOAD

def handleMessage(self):
"""
Called when websocket frame is received.
To access the frame data call self.data.

If the frame is Text then self.data is a unicode object.
If the frame is Binary then self.data is a bytearray object.
"""
pass

def handleConnected(self):
"""
Called when a websocket client connects to the server.
"""
pass

def handleClose(self):
"""
Called when a websocket server gets a Close frame from a client.
"""
pass

def _handlePacket(self):
if self.opcode == CLOSE:
pass
elif self.opcode == STREAM:
pass
elif self.opcode == TEXT:
pass
elif self.opcode == BINARY:
pass
elif self.opcode == PONG or self.opcode == PING:
if len(self.data) > 125:
raise Exception('control frame length can not be > 125')
else:
# unknown or reserved opcode so just close
raise Exception('unknown opcode')

if self.opcode == CLOSE:
status = 1000
reason = u''
length = len(self.data)

if length == 0:
pass
elif length >= 2:
status = struct.unpack_from('!H', self.data[:2])[0]
reason = self.data[2:]

if status not in _VALID_STATUS_CODES:
status = 1002

if len(reason) > 0:
try:
reason = reason.decode('utf8', errors='strict')
except:
status = 1002
else:
status = 1002

self.close(status, reason)
return

elif self.fin == 0:
if self.opcode != STREAM:
if self.opcode == PING or self.opcode == PONG:
raise Exception('control messages can not be fragmented')

self.frag_type = self.opcode
self.frag_start = True
self.frag_decoder.reset()

if self.frag_type == TEXT:
self.frag_buffer = []
utf_str = self.frag_decoder.decode(self.data, final = False)
if utf_str:
self.frag_buffer.append(utf_str)
else:
self.frag_buffer = bytearray()
self.frag_buffer.extend(self.data)

else:
if self.frag_start is False:
raise Exception('fragmentation protocol error')

if self.frag_type == TEXT:
utf_str = self.frag_decoder.decode(self.data, final = False)
if utf_str:
self.frag_buffer.append(utf_str)
else:
self.frag_buffer.extend(self.data)

else:
if self.opcode == STREAM:
if self.frag_start is False:
raise Exception('fragmentation protocol error')

if self.frag_type == TEXT:
utf_str = self.frag_decoder.decode(self.data, final = True)
self.frag_buffer.append(utf_str)
self.data = u''.join(self.frag_buffer)
else:
self.frag_buffer.extend(self.data)
self.data = self.frag_buffer

self.handleMessage()

self.frag_decoder.reset()
self.frag_type = BINARY
self.frag_start = False
self.frag_buffer = None

elif self.opcode == PING:
self._sendMessage(False, PONG, self.data)

elif self.opcode == PONG:
pass

else:
if self.frag_start is True:
raise Exception('fragmentation protocol error')

if self.opcode == TEXT:
try:
self.data = self.data.decode('utf8', errors='strict')
except Exception as exp:
raise Exception('invalid utf-8 payload')

self.handleMessage()


def _handleData(self):
# do the HTTP header and handshake
if self.handshaked is False:

data = self.client.recv(self.headertoread)
if not data:
raise Exception("remote socket closed")

else:
# accumulate
self.headerbuffer.extend(data)

if len(self.headerbuffer) >= self.maxheader:
raise Exception('header exceeded allowable size')

# indicates end of HTTP header
if b'\r\n\r\n' in self.headerbuffer:
self.request = HTTPRequest(self.headerbuffer)

# handshake rfc 6455
try:
key = self.request.headers['Sec-WebSocket-Key']
k = key.encode('ascii') + GUID_STR.encode('ascii')
k_s = base64.b64encode(hashlib.sha1(k).digest()).decode('ascii')
hStr = HANDSHAKE_STR % {'acceptstr': k_s}
self.sendq.append((BINARY, hStr.encode('ascii')))
self.handshaked = True
self.handleConnected()
except Exception as e:
raise Exception('handshake failed: %s', str(e))

# else do normal data
else:
data = self.client.recv(8192)
if not data:
raise Exception("remote socket closed")

if VER >= 3:
for d in data:
self._parseMessage(d)
else:
for d in data:
self._parseMessage(ord(d))

def close(self, status = 1000, reason = u''):
"""
Send Close frame to the client. The underlying socket is only closed
when the client acknowledges the Close frame.

status is the closing identifier.
reason is the reason for the close.
"""
try:
if self.closed is False:
close_msg = bytearray()
close_msg.extend(struct.pack("!H", status))
if _check_unicode(reason):
close_msg.extend(reason.encode('utf-8'))
else:
close_msg.extend(reason)

self._sendMessage(False, CLOSE, close_msg)

finally:
self.closed = True


def _sendBuffer(self, buff):
size = len(buff)
tosend = size
already_sent = 0

while tosend > 0:
try:
# i should be able to send a bytearray
sent = self.client.send(buff[already_sent:])
if sent == 0:
raise RuntimeError("socket connection broken")

already_sent += sent
tosend -= sent

except socket.error as e:
# if we have full buffers then wait for them to drain and try again
if e.errno in [errno.EAGAIN, errno.EWOULDBLOCK]:
return buff[already_sent:]
else:
raise e

return None

def sendFragmentStart(self, data):
"""
Send the start of a data fragment stream to a websocket client.
Subsequent data should be sent using sendFragment().
A fragment stream is completed when sendFragmentEnd() is called.

If data is a unicode object then the frame is sent as Text.
If the data is a bytearray object then the frame is sent as Binary.
"""
opcode = BINARY
if _check_unicode(data):
opcode = TEXT
self._sendMessage(True, opcode, data)

def sendFragment(self, data):
"""
see sendFragmentStart()

If data is a unicode object then the frame is sent as Text.
If the data is a bytearray object then the frame is sent as Binary.
"""
self._sendMessage(True, STREAM, data)

def sendFragmentEnd(self, data):
"""
see sendFragmentEnd()

If data is a unicode object then the frame is sent as Text.
If the data is a bytearray object then the frame is sent as Binary.
"""
self._sendMessage(False, STREAM, data)

def sendMessage(self, data):
"""
Send websocket data frame to the client.

If data is a unicode object then the frame is sent as Text.
If the data is a bytearray object then the frame is sent as Binary.
"""
opcode = BINARY
if _check_unicode(data):
opcode = TEXT
#ser = serial.Serial('COM4', 2400, timeout=0)
#ser.write(b"Q1\r")
#on= ser.read(100)
#print on
self._sendMessage(False, opcode, data)


def _sendMessage(self, fin, opcode, data):

payload = bytearray()

b1 = 0
b2 = 0
if fin is False:
b1 |= 0x80
b1 |= opcode

if _check_unicode(data):
data = data.encode('utf-8')

length = len(data)
payload.append(b1)

if length <= 125:
b2 |= length
payload.append(b2)

elif length >= 126 and length <= 65535:
b2 |= 126
payload.append(b2)
payload.extend(struct.pack("!H", length))

else:
b2 |= 127
payload.append(b2)
payload.extend(struct.pack("!Q", length))

if length > 0:
payload.extend(data)

self.sendq.append((opcode, payload))


def _parseMessage(self, byte):
# read in the header
if self.state == HEADERB1:

self.fin = byte & 0x80
self.opcode = byte & 0x0F
self.state = HEADERB2

self.index = 0
self.length = 0
self.lengtharray = bytearray()
self.data = bytearray()

rsv = byte & 0x70
if rsv != 0:
raise Exception('RSV bit must be 0')

elif self.state == HEADERB2:
mask = byte & 0x80
length = byte & 0x7F

if self.opcode == PING and length > 125:
raise Exception('ping packet is too large')

if mask == 128:
self.hasmask = True
else:
self.hasmask = False

if length <= 125:
self.length = length

# if we have a mask we must read it
if self.hasmask is True:
self.maskarray = bytearray()
self.state = MASK
else:
# if there is no mask and no payload we are done
if self.length <= 0:
try:
self._handlePacket()
finally:
self.state = self.HEADERB1
self.data = bytearray()

# we have no mask and some payload
else:
#self.index = 0
self.data = bytearray()
self.state = PAYLOAD

elif length == 126:
self.lengtharray = bytearray()
self.state = LENGTHSHORT

elif length == 127:
self.lengtharray = bytearray()
self.state = LENGTHLONG


elif self.state == LENGTHSHORT:
self.lengtharray.append(byte)

if len(self.lengtharray) > 2:
raise Exception('short length exceeded allowable size')

if len(self.lengtharray) == 2:
self.length = struct.unpack_from('!H', self.lengtharray)[0]

if self.hasmask is True:
self.maskarray = bytearray()
self.state = MASK
else:
# if there is no mask and no payload we are done
if self.length <= 0:
try:
self._handlePacket()
finally:
self.state = HEADERB1
self.data = bytearray()

# we have no mask and some payload
else:
#self.index = 0
self.data = bytearray()
self.state = PAYLOAD

elif self.state == LENGTHLONG:

self.lengtharray.append(byte)

if len(self.lengtharray) > 8:
raise Exception('long length exceeded allowable size')

if len(self.lengtharray) == 8:
self.length = struct.unpack_from('!Q', self.lengtharray)[0]

if self.hasmask is True:
self.maskarray = bytearray()
self.state = MASK
else:
# if there is no mask and no payload we are done
if self.length <= 0:
try:
self._handlePacket()
finally:
self.state = HEADERB1
self.data = bytearray()

# we have no mask and some payload
else:
#self.index = 0
self.data = bytearray()
self.state = PAYLOAD

# MASK STATE
elif self.state == MASK:
self.maskarray.append(byte)

if len(self.maskarray) > 4:
raise Exception('mask exceeded allowable size')

if len(self.maskarray) == 4:
# if there is no mask and no payload we are done
if self.length <= 0:
try:
self._handlePacket()
finally:
self.state = HEADERB1
self.data = bytearray()

# we have no mask and some payload
else:
#self.index = 0
self.data = bytearray()
self.state = PAYLOAD

# PAYLOAD STATE
elif self.state == PAYLOAD:
if self.hasmask is True:
self.data.append( byte ^ self.maskarray[self.index % 4] )
else:
self.data.append( byte )

# if length exceeds allowable size then we except and remove the connection
if len(self.data) >= self.maxpayload:
raise Exception('payload exceeded allowable size')

# check if we have processed length bytes; if so we are done
if (self.index+1) == self.length:
try:
self._handlePacket()
finally:
#self.index = 0
self.state = HEADERB1
self.data = bytearray()
else:
self.index += 1


class SimpleWebSocketServer(object):
def __init__(self, host, port, websocketclass, selectInterval = None):
self.websocketclass = websocketclass
self.serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.serversocket.bind((host, port))
self.serversocket.listen(5)
self.selectInterval = selectInterval
self.connections = {}
self.listeners = [self.serversocket]
def _decorateSocket(self, sock):
return sock

def _constructWebSocket(self, sock, address):
return self.websocketclass(self, sock, address)

def close(self):
self.serversocket.close()

for desc, conn in self.connections.items():
conn.close()
try:
conn.handleClose()
except:
pass

def serveforever(self):
while True:
writers = []
for fileno in self.listeners:
try:
client = self.connections[fileno]
if client.sendq:
writers.append(fileno)
print writers
except Exception as n:
pass

if self.selectInterval:
rList, wList, xList = select(self.listeners, writers, self.listeners, self.selectInterval)
else:
rList, wList, xList = select(self.listeners, writers, self.listeners)

for ready in wList:
client = None
try:
client = self.connections[ready]
while client.sendq:
opcode, payload = client.sendq.popleft()
remaining = client._sendBuffer(payload)
print opcode, remaining
if remaining is not None:
client.sendq.appendleft((opcode, remaining))
break
else:
if opcode == CLOSE:
raise Exception("received client close")

except Exception as n:

if client:
client.client.close()

try:
if client:
client.handleClose()
except:
pass

try:
del self.connections[ready]
except:
pass

try:
self.listeners.remove(ready)
except:
pass

for ready in rList:
if ready == self.serversocket:
try:
sock, address = self.serversocket.accept()
newsock = self._decorateSocket(sock)
newsock.setblocking(0)
fileno = newsock.fileno()
self.listeners.append(fileno)
self.connections[fileno] = self._constructWebSocket(newsock, address)
except Exception as n:
if sock is not None:
sock.close()
else:
client = None
try:
client = self.connections[ready]
client._handleData()
except Exception as n:
if client:
client.client.close()

try:
if client:
client.handleClose()
except:
pass

try:
del self.connections[ready]
except:
pass

try:
self.listeners.remove(ready)
except:
pass

for failed in xList:
if failed == self.serversocket:
self.close()
raise Exception("server socket failed")
else:
client = None
try:
client = self.connections[failed]
client.client.close()

try:
client.handleClose()
except:
pass

try:
self.listeners.remove(failed)
except:
pass

except:
pass

finally:
if client:
del self.connections[failed]

class SimpleSSLWebSocketServer(SimpleWebSocketServer):

def __init__(self, host, port, websocketclass, certfile, keyfile, version = ssl.PROTOCOL_TLSv1):

SimpleWebSocketServer.__init__(self, host, port, websocketclass)

self.cerfile = certfile
self.keyfile = keyfile
self.version = version

def close(self):
super(SimpleSSLWebSocketServer, self).close()

def _decorateSocket(self, sock):
sslsock = ssl.wrap_socket(sock,
server_side=True,
certfile=self.cerfile,
keyfile=self.keyfile,
ssl_version=self.version)
return sslsock

def _constructWebSocket(self, sock, address):
ws = self.websocketclass(self, sock, address)
ws.usingssl = True
return ws

def serveforever(self):
super(SimpleSSLWebSocketServer, self).serveforever()


////// клиент






WebSocket Test



























здесь если запускается скрипт бес параметров то срабатывает класс SimpleEcho в этом случае как я понял когда я отсылаю данные сокето, после этого принимаю их обработанными, вот я пытаюсь сделать что бы он получал эти данные от бесперебойника, пытался встроить скрипт который работает с беспребойником в скрипт сокета, ничего не выходит, получаю на выходе js object blob, не знаю как сним работать, есть мысль поднять паралельно еще один клиент сокета на питон который будет передавать данные от бесперебойника сокету, то же не получается реализовать, подскажите как сделать вроде бы решение рядом, но не могу до конца понять как это все работает. Спасибо!

Новый ответ

Ответить