pythonnotinlisten
1. python怎么连接websocket
不知道是不是要server和client。
给一个例子,基于py27的聊天室,有server,同时client是用python模拟的,如果你想用js写,可以自己写一个
使用前先:
pip install websocket-client
然后运行server、client就可以了
websocket_server.py(服务端)
#-*-encoding:utf-8-*-
importsys
sys.path.append("..")
fromsocketimport*
importjson,time,threading
reload(sys)
sys.setdefaultencoding("utf8")
config={
'HOST':'127.0.0.1',
'PORT':10010,
'LISTEN_CLIENT':50,
'KEY':'',
'SIZE':2048,
'TIME_OUT':10000,
'HEART_TIME':5,
'MAGIC_STRING':'258EAFA5-E914-47DA-95CA-C5AB0DC85B11',
'HANDSHAKE_STRING':"HTTP/1.1101SwitchingProtocols "
"Upgrade:websocket "
"Connection:Upgrade "
"Sec-WebSocket-Accept:{1} "
"WebSocket-Location:ws://{2}/chat "
"WebSocket-Protocol:chat "
}
classServer():
"""
服务端基类
"""
def__init__(self):
self.sock=socket(AF_INET,SOCK_STREAM)
self.sock.bind((config['HOST'],config['PORT']))#监听端口
self.sock.listen(config['LISTEN_CLIENT'])#监听客户端数量
#所有监听的客户端
self.clients={}
self.thrs={}
self.users={}
self.stops=[]
self.onlineusers=[]
#监听客户端连接
deflisten_client(self):
while1:
#循环监听
tcpClientSock,addr=self.sock.accept()
address=addr[0]+':'+str(addr[1])#ip:port
#握手
topInfo=tcpClientSock.recv(1024)
headers={}
ifnottopInfo:
self.onlineusers.remove(self.users[address])
tcpClientSock.close()
continue
header,data=topInfo.split(' ',1)
try:
getInfo=header.split(' ')[0].split('')[1].split('/')[1:]
ifgetInfo[0]=='name':
self.users[address]=str(getInfo[1])
self.onlineusers.append(self.users[address])
else:
self.users[address]=u'匿名用户'
except:
self.users[address]=u'匿名用户'
print"thisisself.users[address]:"
printself.users[address]
forlineinheader.split(' ')[1:]:
key,val=line.split(':',1)
headers[key]=val
if'Sec-WebSocket-Key'notinheaders:
self.onlineusers.remove(self.users[address])
tcpClientSock.close()
continue
importhashlib,base64
sec_key=headers['Sec-WebSocket-Key']
res_key=base64.b64encode(hashlib.sha1(sec_key+config['MAGIC_STRING']).digest())
str_handshake=config['HANDSHAKE_STRING'].replace('{1}',res_key).replace('{2}',config['HOST']+':'+str(config['PORT']))
tcpClientSock.send(str_handshake)
#握手成功分配线程进行监听
print(address+u'进来了')
self.clients[address]=tcpClientSock
self.thrs[address]=threading.Thread(target=self.readMsg,args=[address])
self.thrs[address].start()
time.sleep(0.5)
defreadMsg(self,address):
ifaddressnotinself.clients:
returnFalse
client=self.clients[address]
importselect
time_out=0
while1:
ifaddressinself.stops:
self.close_client(address)
print(address+u'已经离开了系统!')
break
#检测超时
iftime_out>=config['TIME_OUT']:
self.close_client(address)
break
time_out+=5
infds,outfds,errfds=select.select([client,],[],[],5)
iflen(infds)==0:
continue
time_out=0
try:
info=client.recv(1024)
except:
self.close_client(address)
break
ifnotinfo:
continue
ifinfo=='quit':
self.close_client(address)
break
code_len=ord(info[1])&127
ifcode_len==126:
masks=info[4:8]
data=info[8:]
elifcode_len==127:
masks=info[10:14]
data=info[14:]
else:
masks=info[2:6]
data=info[6:]
i=0
raw_str=""
fordindata:
#print(masks,masks[i%4])
raw_str+=chr(ord(d)^ord(masks[i%4]))
i+=1
print"thisisraw_stryesthisisraw_str"
printrepr(raw_str)
#获取到输入的数据向所有的客户端发送
#开启线程记录
ifraw_str:
t1=threading.Thread(target=self.send_data,args=[raw_str,address])
t1.start()
time.sleep(0.5)defonlineuser(self):
fromurllibimportunquote
username=[]
foriinself.onlineusers:
i=unquote(i).encode('utf8')
username.append(str(i))
returnusername
defsend_data(self,data,address):
importstruct
fromurllibimportunquote
try:
username=unquote(self.users[address])
except:
username=u'匿名用户'
'''封装数据'''
reply={}
ifdata:
data=data.split("}")[0]+"}"
data=json.loads(data);
'''如果有人加入的话,消息封装如下:'''
ifdata["type"]=="JOIN":
reply["type"]="JOIN"
reply["data"]=data["username"]
reply["user_from"]=data["username"]
reply["user"]=self.onlineuser()
'''如果有人发消息,判断是发送给全部还是个人'''
elifdata["type"]=="POST":
reply["type"]="POST"
ifdata["sendto"]=="ALL":
reply["data"]="["+data['username']+"]:"+data["content"]
else:
reply["data"]=u"["+data['username']+"]悄悄对["+data["sendto"]+"]说:"+data["content"]
reply["user_from"]=data["username"]
reply["user"]=self.onlineuser()
reply["sendto"]=data["sendto"]
'''如果是退出的消息,封装如下'''
elifdata["type"]=="QUIT":
self.close_client(address)
reply["type"]="QUIT"
reply["user_from"]=data["username"]
reply["user"]=self.onlineuser()
reply=json.mps(reply)
else:
returnFalse
token="x81"
length=len(reply)
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,或网络流的形式。
alldata='%s%s'%(token,reply)
try:
#判断消息如果是私聊的,找出sendto和sendfrom进行单发
ifdata["type"]=="POST":
ifdata["sendto"]!="ALL":
forkey,valinself.users.iteritems():
printkey,unquote(val)
val=unquote(val)
ifval==data["sendto"]orval==data["username"]:
printkey
self.clients[key].send(alldata)
else:
forkey,valinself.clients.iteritems():
client=val
try:
client.send(alldata)
except:
self.close_client(key)
else:
forkey,valinself.clients.iteritems():
client=val
try:
client.send(alldata)
except:
self.close_client(key)
except:
pass
defclose_client(self,address):
try:
client=self.clients.pop(address)
self.stops.append(address)
self.onlineusers.remove(self.users[address])
client.close()
delself.users[address]
except:
pass
print(address+u'已经退出')if__name__=='__main__':
s=Server()
s.listen_client()websocket_client.py(客户端)
#-*-encoding:utf-8-*-
importsys
sys.path.append("..")
fromsocketimport*
importjson,time,threading
fromwebsocketimportcreate_connection
reload(sys)
sys.setdefaultencoding("utf8")
#config={
#'HOST':'127.0.0.1',
#'PORT':10010
#}
#pipinstallwebsocket-client
classClient():
def__init__(self):
#调用create_connection方法,建立一个websocket链接
self.ws=create_connection("ws://127.0.0.1:10010/name/johanna")
#建一个线程,监听服务器发送给客户端的数据
self.trecv=threading.Thread(target=self.recv)
self.trecv.start()
#建立链接后,给聊天室大家群发一个加入消息
msg={
"type":"JOIN",
"username":"johanna",
"content":"HelloEvery,anewguycomein"
}
msg=json.mps(msg)
self.ws.send(msg)
#发送方法,聊天输入语句时调用,此处默认为群聊ALL
defsend(self,content):
msg={
"type":"POST",
"username":"johanna",
"sendto":"ALL",
"content":content
}
msg=json.mps(msg)
self.ws.send(msg)
#接收服务端发送给客户的数据,只要ws处于连接状态,则一直接收数据
defrecv(self):
try:
whileself.ws.connected:
result=self.ws.recv()
print"receivedmsg:"+str(result)
exceptException,e:
pass
#关闭时,发送QUIT方法,并告诉大家,我要走了
defclose(self):
msg={
"type":"QUIT",
"username":"johanna",
"content":"byebye,everyone"
}
msg=json.mps(msg)
self.ws.send(msg)
if__name__=='__main__':
c=Client()
#当输入聊天语句非exit时,则持续聊天状态,如果exit,则关闭链接
whileTrue:
content=raw_input("pleaseinput(inputexittoexit):")
ifcontent=="exit":
c.close()
break
else:
c.send(content)
time.sleep(1)
2. 小白求教,Python3实例类调用显示没定义
问下你的上述类代码与main代码都在同一个文件里吗,如果在不同文件,有没有import?
3. python3问题
1:
def is_anagram(word1, word2):
return not set(word1) ^ set(word2)
def main():
word1 = input("Enter the first string: ")
word2 = input("Enter the second string: ")
print("listen and silent are %s anagrams." % (
"" if is_anagram(word1, word2) else "not"))
if __name__ == "__main__":
main()
2:
def _list(number_list):
# Write your function code here
return [x[:] for x in number_list[:]]
def main():
number_list = [[1, 2, 3], [4, 5, 6], [8, 9], [10]]
new_list = _list(number_list)
print(number_list)
print(new_list)
number_list.pop()
new_list[0].append([11, 12])
print(number_list)
print(new_list)
4. 如何用Python编写一个聊天室
聊天窗口效果图:
classChatFrame(wx.Frame):"""聊天窗口"""def__init__(self,parent,id,title,size):'初始化,添加控件并绑定事件'wx.Frame.__init__(self,parent,id,title)self.SetSize(size)self.Center()self.chatFrame=wx.TextCtrl(self,pos=(5,5),size=(490,310),style=wx.TE_MULTILINE|wx.TE_READONLY)self.message=wx.TextCtrl(self,pos=(5,320),size=(300,25))self.sendButton=wx.Button(self,label="Send",pos=(310,320),size=(58,25))self.usersButton=wx.Button(self,label="Users",pos=(373,320),size=(58,25))self.closeButton=wx.Button(self,label="Close",pos=(436,320),size=(58,25))self.sendButton.Bind(wx.EVT_BUTTON,self.send)self.usersButton.Bind(wx.EVT_BUTTON,self.lookUsers)self.closeButton.Bind(wx.EVT_BUTTON,self.close)thread.start_new_thread(self.receive,())self.Show()defsend(self,event):'发送消息'message=str(self.message.GetLineText(0)).strip()ifmessage!='':con.write('say'+message+'n')self.message.Clear()deflookUsers(self,event):'查看当前在线用户'con.write('lookn')defclose(self,event):'关闭窗口'con.write('logoutn')con.close()self.Close()defreceive(self):'接受服务器的消息'whileTrue:sleep(0.6)result=con.read_very_eager()ifresult!='':self.chatFrame.AppendText(result)
3.客户端完整代码
#!/usr/bin/python#encoding:utf-(wx.Frame):"""登录窗口"""def__init__(self,parent,id,title,size):'初始化,添加控件并绑定事件'wx.Frame.__init__(self,parent,id,title)self.SetSize(size)self.Center()self.serverAddressLabel=wx.StaticText(self,label="ServerAddress",pos=(10,50),size=(120,25))self.userNameLabel=wx.StaticText(self,label="UserName",pos=(40,100),size=(120,25))self.serverAddress=wx.TextCtrl(self,pos=(120,47),size=(150,25))self.userName=wx.TextCtrl(self,pos=(120,97),size=(150,25))self.loginButton=wx.Button(self,label='Login',pos=(80,145),size=(130,30))self.loginButton.Bind(wx.EVT_BUTTON,self.login)self.Show()deflogin(self,event):'登录处理'try:serverAddress=self.serverAddress.GetLineText(0).split(':')con.open(serverAddress[0],port=int(serverAddress[1]),timeout=10)response=con.read_some()ifresponse!='ConnectSuccess':self.showDialog('Error','ConnectFail!',(95,20))returncon.write('login'+str(self.userName.GetLineText(0))+'n')response=con.read_some()ifresponse=='UserNameEmpty':self.showDialog('Error','UserNameEmpty!',(135,20))elifresponse=='UserNameExist':self.showDialog('Error','UserNameExist!',(135,20))else:self.Close()ChatFrame(None,-2,title='ShiYanLouChatClient',size=(500,350))exceptException:self.showDialog('Error','ConnectFail!',(95,20))defshowDialog(self,title,content,size):'显示错误信息对话框'dialog=wx.Dialog(self,title=title,size=size)dialog.Center()wx.StaticText(dialog,label=content)dialog.ShowModal()classChatFrame(wx.Frame):"""聊天窗口"""def__init__(self,parent,id,title,size):'初始化,添加控件并绑定事件'wx.Frame.__init__(self,parent,id,title)self.SetSize(size)self.Center()self.chatFrame=wx.TextCtrl(self,pos=(5,5),size=(490,310),style=wx.TE_MULTILINE|wx.TE_READONLY)self.message=wx.TextCtrl(self,pos=(5,320),size=(300,25))self.sendButton=wx.Button(self,label="Send",pos=(310,320),size=(58,25))self.usersButton=wx.Button(self,label="Users",pos=(373,320),size=(58,25))self.closeButton=wx.Button(self,label="Close",pos=(436,320),size=(58,25))self.sendButton.Bind(wx.EVT_BUTTON,self.send)self.usersButton.Bind(wx.EVT_BUTTON,self.lookUsers)self.closeButton.Bind(wx.EVT_BUTTON,self.close)thread.start_new_thread(self.receive,())self.Show()defsend(self,event):'发送消息'message=str(self.message.GetLineText(0)).strip()ifmessage!='':con.write('say'+message+'n')self.message.Clear()deflookUsers(self,event):'查看当前在线用户'con.write('lookn')defclose(self,event):'关闭窗口'con.write('logoutn')con.close()self.Close()defreceive(self):'接受服务器的消息'whileTrue:sleep(0.6)result=con.read_very_eager()ifresult!='':self.chatFrame.AppendText(result)'程序运行'if__name__=='__main__':app=wx.App()con=telnetlib.Telnet()LoginFrame(None,-1,title="Login",size=(280,200))app.MainLoop()
5. python ftp permission denied怎么解决
FTP 550 Permission denied 只能建文件夹,没法删除及上传文件的解决方法,需要的朋友可以参考下。
出现这种问题,
①首先检查用户对应的角色名,然后看路径设置是否正确,有没有相关的权限,如果这些都没问题,然后就尝试下面的操作:
②重起FTP服务,最好从服务里面重启(不能根本解决);
③重新设置Server-U帐号和目录访问里的文件路径(如果还不行,尝试下面操作);
④删除用户,重新建。
原创 SU整理(FTP)收藏
整理如下:
1开头-成功
2开头-成功
3开头-权限问题
4开头-文件问题
5开头-服务器问题
150 FILE: %s
150 Opening %s mode data connection for %s (%I64d Bytes).
150 Opening %s mode data connection for %s.
150 Opening ASCII mode data connection for /bin/ls.
150 Opening BINARY mode data connection for MLSD.
200 (end of 'index %s')
200 Command channel switched to clear-text.
200 Command OK, %I64d Bytes available on %s
200 Command okay.
200 EXEC command successful (TID=%u).
200 Message received okay.
200 MLST OPTS
200 MODE S ok.
200 MODE Z LEVEL set to %d.
200 MODE Z ok.
200 Noted.
200 Opened OK (but not really).
200 PBSZ command OK. Protection buffer size set to 0.
200 PBSZ=0
200 PORT Command successful.
200 PROT command OK. Using clear data connection.
200 PROT command OK. Using private data connection.
200 SSCN:CLIENT METHOD
200 SSCN:SERVER METHOD
200 STRU F ok.
200 STRU R ok.
200 Transfer progress notification is off.
200 Transfer progress notification is on.
200 Type set to A.
200 Type set to I.
202 Command not implemented, superfluous at this site.
202 Command not implemented, superfluous at this site.
210 UTC%+ld
211 End
211 End of status.
211-Extension supported
211-Status for user %Name from %IP:
213 %I64d
213 %s
214 Direct comments or bugs to [email protected].
214- The following commands are recognized (* => unimplemented).
215 UNIX Type: L8
220 Service ready for new user.
220 Serv-U FTP Server v%s for WinSock ready...
221 Goodbye!
226 ABOR command successful.
226 Transfer complete.
226 Transfer complete.
226 Transfer complete.
227 Entering Passive Mode (%d,%d,%d,%d,%d,%d)
230 Password changed okay.
230 Switching to SYSTEM MAINTENANCE mode.
230 User logged in, proceed.
230 User logged in.
231 Switching to GROUP MAINTENANCE mode.
232 Switching to DOMAIN MAINTENANCE mode.
233 Switching to READ-ONLY MAINTENANCE mode.
233 User logged in, PASSWORD EXPIRED - please change before proceeding.
234 AUTH command OK. Already have SSL connection.
234 AUTH command OK. Initializing SSL connection.
250 %X
250 DELE command successful.
250 Directory changed to %s
250 End.
250 RMD command successful.
250 RNTO command successful.
250-Listing %s
253 Attributes changed okay.
253 Date/time changed okay.
257 "%s" directory created.
257 "%s" is current directory.
321 Transferred %I64d Bytes.
331 Response to otp-md%d %u %s required for skey.
331 User name okay, need password.
331 User name okay, please send complete E-mail address as password.
350 File or directory exists, ready for destination name
350 Restarting at %I64d. Send STORE or RETRIEVE.
421 Data connection closed (SSL/TLS negotiation failed).
421 Service closing control connection.
425 Cannot open data connection.
425 Cannot open data connection.
425 Cannot open data connection.
425 Try later, data connection in use.
425 Try later, data connection in use.
425 Try later, data connection in use.
425 Try later, out of network sockets.
425 Try later, out of network sockets.
425 Try later, out of network sockets.
425 Unable to listen, too many pending PASV requests from same client IP.
425 Unable to set up passive listening socket.
426 Data connection closed, cannot read file %s.
426 Data connection closed, cannot write file %s - disk full?
426 Data connection closed, error compressing data stream.
426 Data connection closed, error decompressing data stream.
426 Data connection closed, file transfer %s aborted by client.
426 Data connection closed, file transfer %s aborted.
426 Data connection closed, receive file %s aborted.
426 Data connection closed, transfer aborted.
426 Transfer aborted.
431 Account temporarily locked for other user, please try later.
431 Password not changed, no match for old password.
431 Unable to negotiate secure command connection.
432 Password not changed, new password should be at least %d characters in length.
432 Password not changed, new password should contain at least one upper-case character and symbol
432 Password not changed, old and new passwords cannot be identical.
450 Cannot open file %s for reading.
452 Sorry, insufficient disk quota - receive file %s aborted.
500 '%s': command not understood.
501 %s: Not a directory.
501 Cannot EXEC command line (error=%u).
501 Invalid MLST options
501 Invalid option.
501 Not enough space, only %I64d Bytes available on drive %s
501 Permission denied.
501 SITE option not supported.
501 Syntax error in parameters or arguments.
501 Syntax error in parameters or arguments.
501 Syntax error in parameters or arguments.
501 Syntax error in parameters or arguments.
501 Syntax error in parameters or arguments.
501 Syntax error in parameters or arguments.
501 Syntax error in parameters or arguments.
501 Syntax error in parameters or arguments.
501 Syntax error in parameters or arguments.
501 Syntax error in parameters or arguments.
501 Syntax error in parameters or arguments.
501 Syntax error in parameters or arguments.
501 Syntax error in parameters or arguments.
501 Syntax error in parameters or arguments.
501 Syntax error in parameters or arguments.
501 Syntax error in parameters or arguments.
501 Syntax error in parameters or arguments.
501 Syntax error in parameters or arguments.
501 Syntax error in parameters or arguments.
501 Wildcards not allowed.
502 Syntax error - use SITE PSWD "<oldpassword>" "<newpassword>".
503 Bad sequence of commands.
503 Bad sequence of commands.
503 Secure command connection required prior to PBSZ command.
503 Secure command connection required prior to PROT command.
504 Command not implemented for that parameter.
504 Command not implemented for that parameter.
504 Command not implemented for that parameter.
504 Unknown security mechanism.
510 Cannot determine server time zone.
521 Data connection cannot be opened with this PROT setting.
522 SSL/TLS lib refuses to initiate secure data connection.
530 Cannot change Anonymous password.
530 Cannot change password.
530 Not logged in, cannot find home directory.
530 Not logged in, home directory does not exist.
6. python小白一只,请问各位大神,执行以下程序时老是出现以下问题
可以根据以下操作步骤执行:
Traceback (most recent call last):
File "C:/Documents and Settings/Administrator/桌面/11", line 10, in <mole>
sock.bind(DEFAULTADDR)
File "<string>", line 1, in bind
error: (10049, "Can't assign requested address")
回溯(最近一次调用):
文件“C:/文件和设置/管理/桌面/11”,10号线,在<模块>
sock.bind(DEFAULTADDR)
文件“<字符串>”,1号线,在绑定
错误:(10049,“无法分配请求的地址”)
7. 如何用python获取websocket数据
这里,介绍如何使用 Python 与前端 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
<script>
varsocket
= newWebSocket('ws://localhost:3368');
ws.onmessage
= function(result,nTime){
alert("从服务端收到的数据:");
alert("最近一次发送数据到现在接收一共使用时间:"+
nTime);
console.log(result);
}
</script>
8. 如何用Python编写一个聊天室
python聊天室(python2.7版本):
暂时先给出两种版本的,tcp+udp
都是分别运行server.py和client.py,就可以进行通讯了。
别外还有websocket版本,这个是有web界面的和基本web服务的,如果需要的话,我会把基本的代码贴一版上来。
TCP版本:
socket-tcp-server.py(服务端):
#-*-encoding:utf-8-*-
#socket.getaddrinfo(host,port,family=0,socktype=0,proto=0,flags=0)
#根据给定的参数host/port,相应的转换成一个包含用于创建socket对象的五元组,
#参数host为域名,以字符串形式给出代表一个IPV4/IPV6地址或者None.
#参数port如果字符串形式就代表一个服务名,比如“http”"ftp""email"等,或者为数字,或者为None
#参数family为地主族,可以为AF_INET,AF_INET6,AF_UNIX.
#参数socktype可以为SOCK_STREAM(TCP)或者SOCK_DGRAM(UDP)
#参数proto通常为0可以直接忽略
#参数flags为AI_*的组合,比如AI_NUMERICHOST,它会影响函数的返回值
#附注:给参数host,port传递None时建立在C基础,通过传递NULL。
#该函数返回一个五元组(family,socktype,proto,canonname,sockaddr),同时第五个参数sockaddr也是一个二元组(address,port)
#更多的方法及链接请访问
#Echoserverprogram
fromsocketimport*
importsys
importthreading
fromtimeimportctime
fromtimeimportlocaltime
importtraceback
importtime
importsubprocess
reload(sys)
sys.setdefaultencoding("utf8")
HOST='127.0.0.1'
PORT=8555#设置侦听端口
BUFSIZ=1024
classTcpServer():
def__init__(self):
self.ADDR=(HOST,PORT)
try:
self.sock=socket(AF_INET,SOCK_STREAM)
print'%disopen'%PORT
self.sock.bind(self.ADDR)
self.sock.listen(5)
#设置退出条件
self.STOP_CHAT=False
#所有监听的客户端
self.clients={}
self.thrs={}
self.stops=[]
exceptException,e:
print"%disdown"%PORT
returnFalse
defIsOpen(ip,port):
s=socket(AF_INET,SOCK_STREAM)
try:
s.connect((ip,int(port)))
#s.shutdown(2)
#利用shutdown()函数使socket双向数据传输变为单向数据传输。shutdown()需要一个单独的参数,
#该参数表示s了如何关闭socket。具体为:0表示禁止将来读;1表示禁止将来写;2表示禁止将来读和写。
print'%disopen'%port
returnTrue
except:
print'%disdown'%port
returnFalse
deflisten_client(self):
whilenotself.STOP_CHAT:
print(u'等待接入,侦听端口:%d'%(PORT))
self.tcpClientSock,self.addr=self.sock.accept()
print(u'接受连接,客户端地址:',self.addr)
address=self.addr
#将建立的clientsocket链接放到列表self.clients中
self.clients[address]=self.tcpClientSock
#分别将每个建立的链接放入进程中,接收且分发消息
self.thrs[address]=threading.Thread(target=self.readmsg,args=[address])
self.thrs[address].start()
time.sleep(0.5)defreadmsg(self,address):
#如果地址不存在,则返回False
ifaddressnotinself.clients:
returnFalse
#得到发送消息的clientsocket
client=self.clients[address]
whileTrue:
try:
#获取到消息内容data
data=client.recv(BUFSIZ)
except:
print(e)
self.close_client(address)
break
ifnotdata:
break
#python3使用bytes,所以要进行编码
#s='%s发送给我的信息是:[%s]%s'%(addr[0],ctime(),data.decode('utf8'))
#对日期进行一下格式化
ISOTIMEFORMAT='%Y-%m-%d%X'
stime=time.strftime(ISOTIMEFORMAT,localtime())
s=u'%s发送给我的信息是:%s'%(str(address),data.decode('utf8'))
#将获得的消息分发给链接中的clientsocket
forkinself.clients:
self.clients[k].send(s.encode('utf8'))
self.clients[k].sendall('sendall:'+s.encode('utf8'))
printstr(k)
print([stime],':',data.decode('utf8'))
#如果输入quit(忽略大小写),则程序退出
STOP_CHAT=(data.decode('utf8').upper()=="QUIT")
ifSTOP_CHAT:
print"quit"
self.close_client(address)
print"alreadyquit"
break
defclose_client(self,address):
try:
client=self.clients.pop(address)
self.stops.append(address)
client.close()
forkinself.clients:
self.clients[k].send(str(address)+u"已经离开了")
except:
pass
print(str(address)+u'已经退出')
if__name__=='__main__':
tserver=TcpServer()
tserver.listen_client()
——————————华丽的分割线——————————
socket-tcp-client.py(客户端):
#-*-encoding:utf-8-*-
fromsocketimport*
importsys
importthreading
importtime
reload(sys)
sys.setdefaultencoding("utf8")
#测试,连接本机
HOST='127.0.0.1'
#设置侦听端口
PORT=8555
BUFSIZ=1024
classTcpClient:
ADDR=(HOST,PORT)
def__init__(self):
self.HOST=HOST
self.PORT=PORT
self.BUFSIZ=BUFSIZ
#创建socket连接
self.client=socket(AF_INET,SOCK_STREAM)
self.client.connect(self.ADDR)
#起一个线程,监听接收的信息
self.trecv=threading.Thread(target=self.recvmsg)
self.trecv.start()
defsendmsg(self):
#循环发送聊天消息,如果socket连接存在则一直循环,发送quit时关闭链接
whileself.client.connect_ex(self.ADDR):
data=raw_input('>:')
ifnotdata:
break
self.client.send(data.encode('utf8'))
print(u'发送信息到%s:%s'%(self.HOST,data))
ifdata.upper()=="QUIT":
self.client.close()
printu"已关闭"
break
defrecvmsg(self):
#接收消息,如果链接一直存在,则持续监听接收消息
try:
whileself.client.connect_ex(self.ADDR):
data=self.client.recv(self.BUFSIZ)
print(u'从%s收到信息:%s'%(self.HOST,data.decode('utf8')))
exceptException,e:
printstr(e)
if__name__=='__main__':
client=TcpClient()
client.sendmsg()
UDP版本:
socket-udp-server.py
#-*-coding:utf8-*-
importsys
importtime
importtraceback
importthreading
reload(sys)
sys.setdefaultencoding('utf-8')
importsocket
importtraceback
HOST="127.0.0.1"
PORT=9555
CHECK_PERIOD=20
CHECK_TIMEOUT=15
classUdpServer(object):
def__init__(self):
self.clients=[]
self.beats={}
self.ADDR=(HOST,PORT)
try:
self.sock=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
self.sock.bind(self.ADDR)#绑定同一个域名下的所有机器
self.beattrs=threading.Thread(target=self.checkheartbeat)
self.beattrs.start()
exceptException,e:
traceback.print_exc()
returnFalse
deflisten_client(self):
whileTrue:
time.sleep(0.5)
print"hohohohohoo"
try:
recvData,address=self.sock.recvfrom(2048)
ifnotrecvData:
self.close_client(address)
break
ifaddressinself.clients:
senddata=u"%s发送给我的信息是:%s"%(str(address),recvData.decode('utf8'))
ifrecvData.upper()=="QUIT":
self.close_client(address)
ifrecvData=="HEARTBEAT":
self.heartbeat(address)
continue
else:
self.clients.append(address)
senddata=u"%s发送给我的信息是:%s"%(str(address),u'进入了聊天室')
forcinself.clients:
try:
self.sock.sendto(senddata,c)
exceptException,e:
printstr(e)
self.close_client(c)
exceptException,e:
#traceback.print_exc()
printstr(e)
pass
defheartbeat(self,address):
self.beats[address]=time.time()
defcheckheartbeat(self):
whileTrue:
print"checkheartbeat"
printself.beats
try:
forcinself.clients:
printtime.time()
printself.beats[c]
ifself.beats[c]+CHECK_TIMEOUT<time.time():
printu"%s心跳超时,连接已经断开"%str(c)
self.close_client(c)
else:
printu"checkp%s,没有断开"%str(c)
exceptException,e:
traceback.print_exc()
printstr(e)
pass
time.sleep(CHECK_PERIOD)
defclose_client(self,address):
try:
ifaddressinself.clients:
self.clients.remove(address)
ifself.beats.has_key(address):
delself.beats[address]
printself.clients
forcinself.clients:
self.sock.sendto(u'%s已经离开了'%str(address),c)
print(str(address)+u'已经退出')
exceptException,e:
printstr(e)
raise
if__name__=="__main__":
udpServer=UdpServer()
udpServer.listen_client()
——————————华丽的分割线——————————
socket-udp-client.py:
#-*-coding:utf8-*-
importsys
importthreading
importtime
reload(sys)
sys.setdefaultencoding('utf-8')
importsocket
HOST="127.0.0.1"
PORT=9555
#BEAT_PORT=43278
BEAT_PERIOD=5
classUdpClient(object):
def__init__(self):
self.clientsock=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
self.HOST=HOST
self.ADDR=(HOST,PORT)
self.clientsock.sendto(u'请求建立链接',self.ADDR)
self.recvtrs=threading.Thread(target=self.recvmsg)
self.recvtrs.start()
self.hearttrs=threading.Thread(target=self.heartbeat)
self.hearttrs.start()
defsendmsg(self):
whileTrue:
data=raw_input(">:")
ifnotdata:
break
self.clientsock.sendto(data.encode('utf-8'),self.ADDR)
ifdata.upper()=='QUIT':
self.clientsock.close()
break
defheartbeat(self):
whileTrue:
self.clientsock.sendto('HEARTBEAT',self.ADDR)
time.sleep(BEAT_PERIOD)
defrecvmsg(self):
whileTrue:
recvData,addr=self.clientsock.recvfrom(1024)
ifnotrecvData:
break
print(u'从%s收到信息:%s'%(self.HOST,recvData.decode('utf8')))if__name__=="__main__":
udpClient=UdpClient()
udpClient.sendmsg()
9. 两个python问题
#1.t.Usethefollowingfunctionheader:
#defeliminate_plicates(my_list):
#Write
#,
#,callsthefunction
#(eliminate_plicates)
#thefunction.
#:
defeliminate_plicates(my_list):
#Writethefunctioncodehere
rtLst=[]
foriteminmy_list:
ifitemnotinrtLst:
rtLst.append(item)
returnrtLst
defmain():
#Writethemainfunction
strNum=raw_input("")
strNumSplit=strNum.split('')
iNumSplit=[]
foriteminstrNumSplit:
iNumSplit.append(ord(item)-ord('0'))
printeliminate_plicates(iNumSplit)
#Callthemainfunction
main()
#2.Write
#
#iftheyareandFalsetheyarenot.Twowordsareanagramsifthey
#containthesameletters.Forexample,"silent"and"listen"are
#anagrams.Usethefollowingfunctionheader:
#jdefis_anagram(word1,word2):
#Writeamainfunction
#,callstheis_anagram
#.
defis_anagram(word1,word2):
#Writethefunctioncodehere
iflen(word1)!=len(word2):
returnFalse
lstFirst=[]
forcharinword1:
lstFirst.append(char)
lstSecond=[]
forcharinword2:
lstSecond.append(char)
foritem1inlstFirst:
iflstSecond.count(item1)!=1:
returnFalse
returnTrue
defmain():
#Writethemainfunction
strFirst=raw_input("TheFirst: ")
strSecond=raw_input("TheSecond: ")
printis_anagram(strFirst,strSecond)
#Callthemainfunction
main()
10. python怎么建立socket服务端
socket服务器再细分可分为多种了,tcp,udp,websocket,都是调用socket模块,但是具体实现起来有一点细微的差别
先给出一个tcp和udp通过socket协议实现的聊天室的例子
python聊天室(python2.7版本):
都是分别运行server.py和client.py,就可以进行通讯了。
TCP版本:
socket-tcp-server.py(服务端):
#-*-encoding:utf-8-*-
#socket.getaddrinfo(host,port,family=0,socktype=0,proto=0,flags=0)
#根据给定的参数host/port,相应的转换成一个包含用于创建socket对象的五元组,
#参数host为域名,以字符串形式给出代表一个IPV4/IPV6地址或者None.
#参数port如果字符串形式就代表一个服务名,比如“http”"ftp""email"等,或者为数字,或者为None
#参数family为地主族,可以为AF_INET,AF_INET6,AF_UNIX.
#参数socktype可以为SOCK_STREAM(TCP)或者SOCK_DGRAM(UDP)
#参数proto通常为0可以直接忽略
#参数flags为AI_*的组合,比如AI_NUMERICHOST,它会影响函数的返回值
#附注:给参数host,port传递None时建立在C基础,通过传递NULL。
#该函数返回一个五元组(family,socktype,proto,canonname,sockaddr),同时第五个参数sockaddr也是一个二元组(address,port)
#更多的方法及链接请访问
#Echoserverprogram
fromsocketimport*
importsys
importthreading
fromtimeimportctime
fromtimeimportlocaltime
importtraceback
importtime
importsubprocess
reload(sys)
sys.setdefaultencoding("utf8")
HOST='127.0.0.1'
PORT=8555#设置侦听端口
BUFSIZ=1024
classTcpServer():
def__init__(self):
self.ADDR=(HOST,PORT)
try:
self.sock=socket(AF_INET,SOCK_STREAM)
print'%disopen'%PORT
self.sock.bind(self.ADDR)
self.sock.listen(5)
#设置退出条件
self.STOP_CHAT=False
#所有监听的客户端
self.clients={}
self.thrs={}
self.stops=[]
exceptException,e:
print"%disdown"%PORT
returnFalse
defIsOpen(ip,port):
s=socket(AF_INET,SOCK_STREAM)
try:
s.connect((ip,int(port)))
#s.shutdown(2)
#利用shutdown()函数使socket双向数据传输变为单向数据传输。shutdown()需要一个单独的参数,
#该参数表示s了如何关闭socket。具体为:0表示禁止将来读;1表示禁止将来写;2表示禁止将来读和写。
print'%disopen'%port
returnTrue
except:
print'%disdown'%port
returnFalse
deflisten_client(self):
whilenotself.STOP_CHAT:
print(u'等待接入,侦听端口:%d'%(PORT))
self.tcpClientSock,self.addr=self.sock.accept()
print(u'接受连接,客户端地址:',self.addr)
address=self.addr
#将建立的clientsocket链接放到列表self.clients中
self.clients[address]=self.tcpClientSock
#分别将每个建立的链接放入进程中,接收且分发消息
self.thrs[address]=threading.Thread(target=self.readmsg,args=[address])
self.thrs[address].start()
time.sleep(0.5)defreadmsg(self,address):
#如果地址不存在,则返回False
ifaddressnotinself.clients:
returnFalse
#得到发送消息的clientsocket
client=self.clients[address]
whileTrue:
try:
#获取到消息内容data
data=client.recv(BUFSIZ)
except:
print(e)
self.close_client(address)
break
ifnotdata:
break
#python3使用bytes,所以要进行编码
#s='%s发送给我的信息是:[%s]%s'%(addr[0],ctime(),data.decode('utf8'))
#对日期进行一下格式化
ISOTIMEFORMAT='%Y-%m-%d%X'
stime=time.strftime(ISOTIMEFORMAT,localtime())
s=u'%s发送给我的信息是:%s'%(str(address),data.decode('utf8'))
#将获得的消息分发给链接中的clientsocket
forkinself.clients:
self.clients[k].send(s.encode('utf8'))
self.clients[k].sendall('sendall:'+s.encode('utf8'))
printstr(k)
print([stime],':',data.decode('utf8'))
#如果输入quit(忽略大小写),则程序退出
STOP_CHAT=(data.decode('utf8').upper()=="QUIT")
ifSTOP_CHAT:
print"quit"
self.close_client(address)
print"alreadyquit"
break
defclose_client(self,address):
try:
client=self.clients.pop(address)
self.stops.append(address)
client.close()
forkinself.clients:
self.clients[k].send(str(address)+u"已经离开了")
except:
pass
print(str(address)+u'已经退出')
if__name__=='__main__':
tserver=TcpServer()
tserver.listen_client()
——————————华丽的分割线——————————
socket-tcp-client.py(客户端):
#-*-encoding:utf-8-*-
fromsocketimport*
importsys
importthreading
importtime
reload(sys)
sys.setdefaultencoding("utf8")
#测试,连接本机
HOST='127.0.0.1'
#设置侦听端口
PORT=8555
BUFSIZ=1024
classTcpClient:
ADDR=(HOST,PORT)
def__init__(self):
self.HOST=HOST
self.PORT=PORT
self.BUFSIZ=BUFSIZ
#创建socket连接
self.client=socket(AF_INET,SOCK_STREAM)
self.client.connect(self.ADDR)
#起一个线程,监听接收的信息
self.trecv=threading.Thread(target=self.recvmsg)
self.trecv.start()
defsendmsg(self):
#循环发送聊天消息,如果socket连接存在则一直循环,发送quit时关闭链接
whileself.client.connect_ex(self.ADDR):
data=raw_input('>:')
ifnotdata:
break
self.client.send(data.encode('utf8'))
print(u'发送信息到%s:%s'%(self.HOST,data))
ifdata.upper()=="QUIT":
self.client.close()
printu"已关闭"
break
defrecvmsg(self):
#接收消息,如果链接一直存在,则持续监听接收消息
try:
whileself.client.connect_ex(self.ADDR):
data=self.client.recv(self.BUFSIZ)
print(u'从%s收到信息:%s'%(self.HOST,data.decode('utf8')))
exceptException,e:
printstr(e)
if__name__=='__main__':
client=TcpClient()
client.sendmsg()
UDP版本:
socket-udp-server.py
#-*-coding:utf8-*-
importsys
importtime
importtraceback
importthreading
reload(sys)
sys.setdefaultencoding('utf-8')
importsocket
importtraceback
HOST="127.0.0.1"
PORT=9555
CHECK_PERIOD=20
CHECK_TIMEOUT=15
classUdpServer(object):
def__init__(self):
self.clients=[]
self.beats={}
self.ADDR=(HOST,PORT)
try:
self.sock=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
self.sock.bind(self.ADDR)#绑定同一个域名下的所有机器
self.beattrs=threading.Thread(target=self.checkheartbeat)
self.beattrs.start()
exceptException,e:
traceback.print_exc()
returnFalse
deflisten_client(self):
whileTrue:
time.sleep(0.5)
print"hohohohohoo"
try:
recvData,address=self.sock.recvfrom(2048)
ifnotrecvData:
self.close_client(address)
break
ifaddressinself.clients:
senddata=u"%s发送给我的信息是:%s"%(str(address),recvData.decode('utf8'))
ifrecvData.upper()=="QUIT":
self.close_client(address)
ifrecvData=="HEARTBEAT":
self.heartbeat(address)
continue
else:
self.clients.append(address)
senddata=u"%s发送给我的信息是:%s"%(str(address),u'进入了聊天室')
forcinself.clients:
try:
self.sock.sendto(senddata,c)
exceptException,e:
printstr(e)
self.close_client(c)
exceptException,e:
#traceback.print_exc()
printstr(e)
pass
defheartbeat(self,address):
self.beats[address]=time.time()
defcheckheartbeat(self):
whileTrue:
print"checkheartbeat"
printself.beats
try:
forcinself.clients:
printtime.time()
printself.beats[c]
ifself.beats[c]+CHECK_TIMEOUT<time.time():
printu"%s心跳超时,连接已经断开"%str(c)
self.close_client(c)
else:
printu"checkp%s,没有断开"%str(c)
exceptException,e:
traceback.print_exc()
printstr(e)
pass
time.sleep(CHECK_PERIOD)
defclose_client(self,address):
try:
ifaddressinself.clients:
self.clients.remove(address)
ifself.beats.has_key(address):
delself.beats[address]
printself.clients
forcinself.clients:
self.sock.sendto(u'%s已经离开了'%str(address),c)
print(str(address)+u'已经退出')
exceptException,e:
printstr(e)
raise
if__name__=="__main__":
udpServer=UdpServer()
udpServer.listen_client()
——————————华丽的分割线——————————
socket-udp-client.py:
#-*-coding:utf8-*-
importsys
importthreading
importtime
reload(sys)
sys.setdefaultencoding('utf-8')
importsocket
HOST="127.0.0.1"
PORT=9555
#BEAT_PORT=43278
BEAT_PERIOD=5
classUdpClient(object):
def__init__(self):
self.clientsock=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
self.HOST=HOST
self.ADDR=(HOST,PORT)
self.clientsock.sendto(u'请求建立链接',self.ADDR)
self.recvtrs=threading.Thread(target=self.recvmsg)
self.recvtrs.start()
self.hearttrs=threading.Thread(target=self.heartbeat)
self.hearttrs.start()
defsendmsg(self):
whileTrue:
data=raw_input(">:")
ifnotdata:
break
self.clientsock.sendto(data.encode('utf-8'),self.ADDR)
ifdata.upper()=='QUIT':
self.clientsock.close()
break
defheartbeat(self):
whileTrue:
self.clientsock.sendto('HEARTBEAT',self.ADDR)
time.sleep(BEAT_PERIOD)
defrecvmsg(self):
whileTrue:
recvData,addr=self.clientsock.recvfrom(1024)
ifnotrecvData:
break
print(u'从%s收到信息:%s'%(self.HOST,recvData.decode('utf8')))if__name__=="__main__":
udpClient=UdpClient()
udpClient.sendmsg()