python 实现新版websocket协议 server - 0x14 - ITeye技术网站
websocket 和 正常 socket 使用方式有点不一样
正常socket 客户端流程:
连接 -> 连接成功 -> 接受数据 || 发送数据
完事了
正常socket 服务端流程:
创建套接字 -> 绑定 -> 接受连接 -> 接受数据 || 发送数据
完事了
websocket 客户端流程:
连接-> 连接成功 -> 创建消息响应事件 -> 发送数据
websocket 服务端流程
创建套接字 -> 绑定 -> 接受连接 -> 接受websocket 发送过来的http头 -> 处理要回应的http头 ->
回应客户端 -> 握手成功 -> 按照websocket数据格式接受发送数据
确实稍微麻烦点
现在开始用python来实现一个websocket server
- import socket,threading,struct
- #启动websocket server
- def InitWebSocketServer():
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- try:
- sock.bind(("localhost",3398)) #绑定本地地址,端口3398
- sock.listen(100)
- except:
- print("Server is already running,quit")
- sys.exit()
- while True: #创建一个死循环,接受客户端
- connection,address = sock.accept()
- if(handshake(connection) != False): #如果握手失败,不启动任务
- t = threading.Thread(target=DoRemoteCommand,args=(connection,))
- t.start()
- #连接成功后回应给客户端进行握手
- def handshake(client):
- headers = {}
- shake = client.recv(1024)
- if not len(shake):
- return False
- header, data = shake.split('\r\n\r\n', 1)
- for line in header.split("\r\n")[1:]:
- key, value = line.split(": ", 1)
- headers[key] = value
- if(headers.has_key("Sec-WebSocket-Key") == False):
- print("this socket is not websocket,close")
- client.close()
- return False
- szOrigin = headers["Sec-WebSocket-Origin"]
- szKey = base64.b64encode(hashlib.sha1(headers["Sec-WebSocket-Key"] + '258EAFA5-E914-47DA-95CA-C5AB0DC85B11').digest())
- szHost = headers["Host"]
- our_handshake = "HTTP/1.1 101 Switching Protocols\r\n" \
- "Upgrade:websocket\r\n"\
- "Connection: Upgrade\r\n"\
- "Sec-WebSocket-Accept:"+ szKey + "\r\n" \
- "WebSocket-Origin:" + szOrigin + "\r\n" \
- "WebSocket-Location: ws://" + szHost + "/WebManagerSocket\r\n" \
- "WebSocket-Protocol:WebManagerSocket\r\n\r\n"
- client.send(our_handshake)
- return True
- #接收客户端发送过来的消息,并且解包
- def RecvData(nNum,client):
- try:
- pData = client.recv(nNum)
- if not len(pData):
- return False
- except:
- return False
- else:
- code_length = ord(pData[1]) & 127
- if code_length == 126:
- masks = pData[4:8]
- data = pData[8:]
- elif code_length == 127:
- masks = pData[10:14]
- data = pData[14:]
- else:
- masks = pData[2:6]
- data = pData[6:]
- raw_str = ""
- i = 0
- for d in data:
- raw_str += chr(ord(d) ^ ord(masks[i%4]))
- i += 1
- return raw_str
- #打包发送数据给客户端
- def SendData(pData,client):
- if(pData == False):
- return False
- else:
- pData = str(pData)
- token = "\x81"
- length = len(pData)
- if length < 126:
- token += struct.pack("B", length)
- elif length <= 0xFFFF:
- token += struct.pack("!BH", 126, length)
- else:
- token += struct.pack("!BQ", 127, length)
- pData = '%s%s' % (token,pData)
- client.send(pData)
- return True
- #这算是客户端一个循环接受数据并且处理数据的线程
- def DoRemoteCommand(connection):
- while 1:
- szBuf = RecvData(8196,connection)
- if(szBuf == False):
- break
对,完了,就这样,启动
- InitWebSocketServer()
然后就可以与chrome和firefox的websocket通信了
客户端的实现可以看我另一篇文章
代码拿来直接就能用,在做项目中,没有这么多时间去系统的学习,有现成的资源就拿去用吧,以上代码实现的是新版的websocket协议,不兼容旧版的,目前网上大部分都是旧版的例子,需要的去找来组合下就可以了.
上面代码只是个草稿,根据自己的情况进行修改,websocket目前只能传输字符串,图片传输等可以使用base64编码后进行发送(数据大小会增加 1/3 左右)
博客地址:http://0x14.iteye.com/