python web服务器怎么获取用户信息_如何用python获取websocket数据

展开全部

这里,介绍如何使用 Python 与前e5a48de588b662616964757a686964616f31333363383463端 js 进行通信。

websocket 使用 HTTP 协议完成握手之后,不通过 HTTP 直接进行 websocket 通信。

于是,使用 websocket 大致两个步骤:使用 HTTP 握手,通信。

js 处理 websocket 要使用 ws 模块; python 处理则使用 socket 模块建立 TCP 连接即可,比一般的 socket ,只多一个握手以及数据处理的步骤。

握手

过程

包格式

js 客户端先向服务器端 python 发送握手包,格式如下:

?

1

2

3

4

5

6

7

8

GET

/chat HTTP/1.1

Host:

server.example.com

Upgrade:

websocket

Connection:

Upgrade

Sec-WebSocket-Key:

dGhlIHNhbXBsZSBub25jZQ==

Origin:

Sec-WebSocket-Protocol:

chat, superchat

Sec-WebSocket-Version:

13

服务器回应包格式:

?

1

2

3

4

5

HTTP/1.1

101 Switching Protocols

Upgrade:

websocket

Connection:

Upgrade

Sec-WebSocket-Accept:

s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

Sec-WebSocket-Protocol:

chat

其中, Sec-WebSocket-Key 是随机的,服务器用这些数据构造一个 SHA-1 信息摘要。

方法为: key+migic , SHA-1 加密, base-64 加密,如下:

Python 中的处理代码

?

1

2

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

res_key=base64.b64encode(hashlib.sha1(sec_key

+MAGIC_STRING).digest())

握手完整代码

js 端

js 中有处理 websocket 的类,初始化后自动发送握手包,如下:

var socket = new WebSocket('ws://localhost:3368');

Python 端

Python 用 socket 接受得到握手字符串,处理后发送

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

HOST='localhost'

PORT=3368

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

HANDSHAKE_STRING="HTTP/1.1

101 Switching Protocols\r\n"

\

"Upgrade:websocket\r\n"\

"Connection:

Upgrade\r\n"

\

"Sec-WebSocket-Accept:

{1}\r\n"

\

"WebSocket-Location:ws://{2}/chat\r\n"

\

"WebSocket-Protocol:chat\r\n\r\n"

defhandshake(con):

#con为用socket,accept()得到的socket

headers={}

shake=con.recv(1024)

ifnot

len(shake):

returnFalse

header,

data =shake.split('\r\n\r\n',1)

forline

inheader.split('\r\n')[1:]:

key,

val =line.split(':

',1)

headers[key]=val

if'Sec-WebSocket-Key'

not

in

headers:

print('This

socket is not websocket, client close.')

con.close()

returnFalse

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

res_key=base64.b64encode(hashlib.sha1(sec_key

+MAGIC_STRING).digest())

str_handshake=HANDSHAKE_STRING.replace('{1}',

res_key).replace('{2}',

HOST +':'

+

str(PORT))

printstr_handshake

con.send(str_handshake)

returnTrue

通信

不同版本的浏览器定义的数据帧格式不同, Python 发送和接收时都要处理得到符合格式的数据包,才能通信。

Python 接收

Python 接收到浏览器发来的数据,要解析后才能得到其中的有用数据。

浏览器包格式

固定字节:

( 1000 0001 或是 1000 0002 )这里没用,忽略

包长度字节:

第一位肯定是 1 ,忽略。剩下 7 个位可以得到一个整数 (0 ~ 127) ,其中

( 1-125 )表此字节为长度字节,大小即为长度;

(126)表接下来的两个字节才是长度;

(127)表接下来的八个字节才是长度;

用这种变长的方式表示数据长度,节省数据位。

mark 掩码:

mark 掩码为包长之后的 4 个字节,之后的兄弟数据要与 mark 掩码做运算才能得到真实的数据。

兄弟数据:

得到真实数据的方法:将兄弟数据的每一位 x ,和掩码的第 i%4 位做 xor 运算,其中 i 是 x 在兄弟数据中的索引。

完整代码

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

defrecv_data(self,

num):

try:

all_data=self.con.recv(num)

ifnot

len(all_data):

returnFalse

except:

returnFalse

else:

code_len=ord(all_data[1])

& 127

ifcode_len

==126:

masks=all_data[4:8]

data=all_data[8:]

elifcode_len

==127:

masks=all_data[10:14]

data=all_data[14:]

else:

masks=all_data[2:6]

data=all_data[6:]

raw_str=""

i=0

ford

indata:

raw_str+=chr(ord(d)

^ ord(masks[i%4]))

i+=1

returnraw_str

js 端的 ws 对象,通过 ws.send(str) 即可发送

ws.send(str)

Python 发送

Python 要包数据发送,也需要处理,发送包格式如下

固定字节:固定的 1000 0001( ‘ \x81 ′ )

包长:根据发送数据长度是否超过 125 , 0xFFFF(65535) 来生成 1 个或 3 个或 9 个字节,来代表数据长度。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

defsend_data(self,

data):

ifdata:

data=str(data)

else:

returnFalse

token="\x81"

length=len(data)

iflength

< 126:

token+=struct.pack("B",

length)

eliflength

<=0xFFFF:

token+=struct.pack("!BH",126,

length)

else:

token+=struct.pack("!BQ",127,

length)

#struct为Python中处理二进制数的模块,二进制流为C,或网络流的形式。

data='%s%s'

%

(token, data)

self.con.send(data)

returnTrue

js 端通过回调函数 ws.onmessage() 接受数据

?

1

2

3

4

5

ws.onmessage

= function(result,nTime){

alert("从服务端收到的数据:");

alert("最近一次发送数据到现在接收一共使用时间:"+

nTime);

console.log(result);

}

最终代码

Python服务端

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

#

_*_ coding:utf-8 _*_

__author__='Patrick'

importsocket

importthreading

importsys

importos

importMySQLdb

importbase64

importhashlib

importstruct

#

====== config ======

HOST='localhost'

PORT=3368

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

HANDSHAKE_STRING="HTTP/1.1

101 Switching Protocols\r\n"

\

"Upgrade:websocket\r\n"\

"Connection:

Upgrade\r\n"

\

"Sec-WebSocket-Accept:

{1}\r\n"

\

"WebSocket-Location:ws://{2}/chat\r\n"

\

"WebSocket-Protocol:chat\r\n\r\n"

classTh(threading.Thread):

def__init__(self,

connection,):

threading.Thread.__init__(self)

self.con=connection

defrun(self):

whileTrue:

try:

pass

self.con.close()

defrecv_data(self,

num):

try:

all_data=self.con.recv(num)

ifnot

len(all_data):

returnFalse

except:

returnFalse

else:

code_len=ord(all_data[1])

& 127

ifcode_len

==126:

masks=all_data[4:8]

data=all_data[8:]

elifcode_len

==127:

masks=all_data[10:14]

data=all_data[14:]

else:

masks=all_data[2:6]

data=all_data[6:]

raw_str=""

i=0

ford

indata:

raw_str+=chr(ord(d)

^ ord(masks[i%4]))

i+=1

returnraw_str

#

send data

defsend_data(self,

data):

ifdata:

data=str(data)

else:

returnFalse

token="\x81"

length=len(data)

iflength

< 126:

token+=struct.pack("B",

length)

eliflength

<=0xFFFF:

token+=struct.pack("!BH",126,

length)

else:

token+=struct.pack("!BQ",127,

length)

#struct为Python中处理二进制数的模块,二进制流为C,或网络流的形式。

data='%s%s'

%

(token, data)

self.con.send(data)

returnTrue

#

handshake

defhandshake(con):

headers={}

shake=con.recv(1024)

ifnot

len(shake):

returnFalse

header,

data =shake.split('\r\n\r\n',1)

forline

inheader.split('\r\n')[1:]:

key,

val =line.split(':

',1)

headers[key]=val

if'Sec-WebSocket-Key'

not

in

headers:

print('This

socket is not websocket, client close.')

con.close()

returnFalse

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

res_key=base64.b64encode(hashlib.sha1(sec_key

+MAGIC_STRING).digest())

str_handshake=HANDSHAKE_STRING.replace('{1}',

res_key).replace('{2}',

HOST +':'

+

str(PORT))

printstr_handshake

con.send(str_handshake)

returnTrue

defnew_service():

"""start

a service socket and listen

when

coms a connection, start a new thread to handle it"""

sock=socket.socket(socket.AF_INET,

socket.SOCK_STREAM)

try:

sock.bind(('localhost',3368))

sock.listen(1000)

#链接队列大小

print"bind

3368,ready to use"

except:

print("Server

is already running,quit")

sys.exit()

whileTrue:

connection,

address =sock.accept()

#返回元组(socket,add),accept调用时会进入waite状态

print"Got

connection from ",

address

ifhandshake(connection):

print"handshake

success"

try:

t=Th(connection,

layout)

t.start()

print'new

thread for client ...'

except:

print'start

new thread error'

connection.close()

if__name__

=='__main__':

new_service()

js客户 端

?

1

2

3

4

5

6

7

8

varsocket

= newWebSocket('ws://localhost:3368');

ws.onmessage

= function(result,nTime){

alert("从服务端收到的数据:");

alert("最近一次发送数据到现在接收一共使用时间:"+

nTime);

console.log(result);

}

2Q==

已赞过

已踩过<

你对这个回答的评价是?

评论

收起

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Python中有很多库可以用来实现WebSocket服务器。其中比较常用的有: 1. `websocket`模块:一个Python WebSocket实现,它包含一个WebSocket服务器和一个WebSocket客户端。它可以与许多不同的浏览器和操作系统一起使用。这个模块的安装方式为: ``` pip install websocket ``` 2. `Tornado`框架:一个Python Web框架,可以用来实现WebSocket服务器。它具有高性能和可扩展性,适用于高并发场景。这个框架的安装方式为: ``` pip install tornado ``` 3. `Django Channels`:一个基于Django框架的WebSocket实现。它支持异步编程,适用于实时通信场景。这个框架的安装方式为: ``` pip install channels ``` 以上三种方法都可以用来实现WebSocket服务器。在实现过程中,我们需要创建一个WebSocket服务器对象,并设置回调函数来处理WebSocket连接、消息接收等事件。 ### 回答2: Python WebSocket服务器是一种Web服务器,它是基于WebSocket协议实现的。WebSocket是一种协议,它可以实现全双工通信,即服务器和客户端可以同时发送和接收数据。在传统的HTTP协议中,由于是单向通信,服务器只能在收到客户端请求后才能发送数据给客户端,而不能主动向客户端发送数据。而WebSocket协议在建立连接后,服务器和客户端可以相互发送数据,不需要再发送HTTP请求。 Python WebSocket服务器可以用于实现实时通信、在线聊天和实时互动等网站功能。在实现这些功能的过程中,服务器可以向客户端实时推送数据,提高用户体验。 在实现Python WebSocket服务器时,可以使用一些现成的库,比如Tornado、Flask-Sockets、gevent-websocket等。这些库都完美地实现了WebSocket协议,并且具有很好的性能和扩展性。其中,Tornado比较成熟,是性能最好的一种Web框架,它提供了WebSocketHandler类,可以快速地实现WebSocket服务器。 使用Python WebSocket服务器不仅可以提高网站的体验,而且可以大大降低开发成本和时间。值得注意的是,在使用WebSocket通信时,需要注意安全性问题,比如防止XSS攻击和CSRF攻击等。因此,在实现Python WebSocket服务器时,需要考虑如何保证通信的安全性,以避免潜在的安全威胁。 ### 回答3: Python WebSocket服务器是一种基于WebSocket协议实现的服务器程序,它可以通过WebSocket协议实现实时数据传输和双向通信。WebSocket协议是一种比传统HTTP协议更加高效的协议,它可以在客户端和服务器之间实现实时通信,且没有HTTP协议所带来的额外开销和延迟。 Python WebSocket服务器有多种实现方式,其中比较流行的有: 1. Tornado Tornado是一个用于构建高效、易于扩展、异步Web应用程序和网络工具的Python Web框架。Tornado提供了异步非阻塞的WebSocket服务器实现,通过使用Tornado的WebSocketHandler,可以轻松实现WebSocket服务器程序。 2. Flask-SocketIO Flask-SocketIO是一个基于Flask的Python WebSocket服务器实现,它集成了Socket.IO,可以为Python Web应用程序添加实时通信功能。 3. Django Channels Django Channels是一个可以为Django应用程序提供实时通信功能的库。它提供了一个基于WebSocket的协议来实现实时通信,同时也支持其他协议,如长轮询和传统的HTTP请求方式。 无论使用哪种Python WebSocket服务器实现方式,都需要注意一些问题: 1. 安全性问题。WebSocket协议开放了一些端口,如果不做好安全措施,可能存在数据泄露和攻击的风险。 2. 性能问题。与HTTP相比,WebSocket协议带宽更大,如果服务器带宽不足,可能导致通信延迟和数据传输不稳定。 3. 支持性问题。WebSocket协议还比较新,不是所有的Web浏览器都支持该协议,需要对不同浏览器做好兼容性处理。 使用Python WebSocket服务器需要对Web开发有一定的经验和技能,需要对WebSocket协议有深入的了解。但是,Python WebSocket服务器是一种非常灵活和方便的实时通信方案,能够为Web应用程序带来更好的用户体验和交互性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值