聊天web项目
来源:互联网 发布:python 图片加水印 编辑:程序博客网 时间:2024/06/12 00:08
# coding: utf-8 from socket import * import json, time, threadingimport structfrom urllib import unquoteconfig = { 'HOST': 'localhost', 'PORT': 11011, 'LISTEN_CLIENT': 50, 'KEY': '391f10fadc339e9ec5fa15af60030ac1', 'SIZE': 2048, 'TIME_OUT': 1000, 'HEART_TIME': 5, '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" } class Server(): """ 服务端基类 """ 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 = [] print u"\n正在监听端口..." # 监听客户端连接 def listen_client(self): while 1: # 循环监听 tcpClientSock,addr = self.sock.accept() address = addr[0] + ':' + str(addr[1]) # ip:port # 握手 topInfo = tcpClientSock.recv(1024) headers = {} #print u'\n服务端发送的信息:', address if not topInfo: tcpClientSock.close() continue header, data = topInfo.split('\r\n\r\n', 1) try: getInfo = header.split('\r\n')[0].split(' ')[1].split('/')[1:] if getInfo[0] == 'name': self.users[address] = str(getInfo[1]) else: self.users[address] = '匿名用户' except: self.users[address] = '匿名用户' for line in header.split('\r\n')[1:]: key, val = line.split(': ', 1) headers[key] = val if 'Sec-WebSocket-Key' not in headers: tcpClientSock.close() continue import hashlib, 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) try: username = unquote(self.users[address]) except: username = '匿名用户' # 握手成功 分配线程进行监听 print u'\n用户: ',username+' 进入了房间',"IP地址为:",address self.clients[address] = tcpClientSock self.thrs[address] = threading.Thread(target=self.readMsg, args=[address]) self.thrs[address].start() #print u"\n:",self.clients def readMsg(self, address): #print u"\n:",self.clients if address not in self.clients: return False client = self.clients[address] import select time_out = 0 try: username = unquote(self.users[address]) except: username = '匿名用户' while 1: # print(len(self.clients)) if address in self.stops: self.close_client(address) print u"\n",username + "已经离开了系统!IP:",address break # 检测超时 if time_out >= config['TIME_OUT']: self.close_client(address) break time_out += 5 infds, outfds, errfds = select.select([client, ], [], [], 5) if len(infds) == 0: continue time_out = 0 try: info = client.recv(1024) except: self.close_client(address) break if not info: continue if info == 'quit': self.close_client(address) break code_len = ord(info[1]) & 127 if code_len == 126: masks = info[4:8] data = info[8:] elif code_len == 127: masks = info[10:14] data = info[14:] else: masks = info[2:6] data = info[6:] i = 0 raw_str = "" for d in data: # print(masks, masks[i % 4]) raw_str += chr(ord(d) ^ ord(masks[i % 4])) # print(raw_str) i += 1 # 获取到输入的数据 向所有的客户端发送 # 开启线程记录 if raw_str: t1 = threading.Thread(target=self.send_data, args=[raw_str, address]) t1.start() def send_data(self, data, address): #import struct #from urllib import unquote try: username = unquote(self.users[address]) except: username = '匿名用户' if data: data = str('【'+username+' 说】:'+data) print u"\n服务端发送的信息为:",data else: return False token = "\x81" length = len(data) if length < 126: token += struct.pack("B", length) elif length <= 0xFFFF: token += struct.pack("!BH", 126, length) else: token += struct.pack("!BQ", 127, length) # struct为Python中处理二进制数的模块,二进制流为C,或网络流的形式。 data = '%s%s' % (token, data) try: for key, val in self.clients.iteritems(): client = val try: client.send(data) except: self.close_client(key) except: pass def close_client(self, address): try: username = unquote(self.users[address]) except: username = '匿名用户' try: client = self.clients.pop(address) self.stops.append(address) client.close() del self.users[address] except: pass print u"\n用户:",username +"已经退出,IP为:",address if __name__ == '__main__': c = Server() c.listen_client()
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>WebSocket</title>
<script src="js/jquery.js" type="text/javascript"></script>
<style>
* {
font-family: "微软雅黑";
margin: 0;
padding: 0;
}
html, body {
width: 100%;
height: 100%;
background: #000;
position: relative;
}
.msgInfo {
position: fixed;
right: 2%;
top: 2%;
height: 96%;
width: 20%;
background: #666;
}
.msgInfo .hd {
width: 100%;
text-align: center;
height: 40px;
line-height: 40px;
color: #fff;
background: #333;
}
.msgInfo .bd {
padding: 20px;
height: 100%;
overflow: auto;
color: #fff;
line-height: 30px;
}
.msgInfo .bd p {
margin: 5px 0;
}
.sendBox {
position: fixed;
left: 2%;
bottom: 2%;
width: 74%;
height: 10%;
background: #666;
overflow: hidden;
}
.sendBox textarea {
width: 90%;
height: 100%;
display: inline-block;
background: #666;
color: #fff;
border: none;
float: left;
}
.sendBox button {
width: 10%;
height: 100%;
display: inline-block;
background: #333;
cursor: pointer;
color: #fff;
border: none;
float: left;
}
.renBox {
margin-left: 2%;
margin-top: 2%;
width: 74%;
height: 84%;
position: relative;
overflow: hidden;
float: left;
}
.renBox .ren {
display: inline-block;
position: absolute;
left: 500px;
top: 500px;
}
.renBox .ren .renHead {
display: inline-block;
width: 20px;
height: 20px;
border-radius: 10px;
background: #fff;
}
.renBox .ren .sayInfo {
color: #fff;
position: absolute;
top: -30px;
width: 200px;
left: -90px;
text-align: center;
}
.renBox div {
color: #fff;
margin-left: 100%;
width: 100%;
overflow: hidden;
height: 30px;
line-height: 30px;
font-size: 20px;
}
.firstStep {
position: fixed;
width: 100%;
height: 100%;
z-index: 999;
background: #000;
text-align: center;
}
.firstStep .firstName {
display: inline-block;
padding-top: 300px;
}
.firstStep .firstName .username {
width: 300px;
height: 40px;
border: 0;
padding: 0 10px;
}
.firstStep .firstName .btn {
width: 100px;
height: 40px;
border: 0;
background: #333;
color: #fff;
cursor: pointer;
}
</style>
<script>
var socket;
function init(username) {
var host = "ws://localhost:11011/name/" + username;
try {
socket = new WebSocket(host);
socket.onopen = function(msg) {
log('您已经进入聊天室')
};
socket.onmessage = function(msg) {
log(msg.data);
};
socket.onclose = function(msg) {
log("与服务器连接断开");
};
} catch (ex) {
log(ex);
}
$(".sendInfo").focus();
}
function send() {
var txt, msg;
txt = $(".sendInfo");
msg = txt.val();
if (!msg) {
alert("发送消息不能为空!");
return;
}
txt.val('');
txt.focus();
try {
socket.send(msg);
$('.sayInfo').html(msg)
// log("我说:"+msg);
} catch (ex) {
log(ex);
}
}
window.onbeforeunload = function() {
try {
socket.send('quit');
socket.close();
socket = null;
} catch (ex) {
log(ex);
}
};
function nameok() {
var _name = $('input[name="username"]').val();
if (!_name) {
alert('请给自己取个名字吧')
} else {
$('.firstStep').remove()
init(_name)
}
}
function log(msg) {
$('.msgInfo .bd').append('<p>' + msg + '</p>');
//动画
var _html = $('<div>', {
'class' : 'showMsg'
});
_html.html(msg);
$('.renBox').append(_html);
_html.animate({
'marginLeft' : '-100%'
}, 10000, function() {
_html.remove()
})
}
function show(obj) {
obj.fadeIn()
}
function onkey(event) {
if (event.keyCode == 13) {
send();
}
}
</script>
<!--<link href="/static/css/css.css" type="text/css" rel="stylesheet" /> -->
</head>
<body>
<div class="renBox">
<!--<div class="ren">-->
<!--<span class="sayInfo"></span>-->
<!--<span class="renHead"></span>-->
<!--</div>-->
</div>
<div class="msgInfo">
<div class="hd">聊天记录</div>
<div class="bd"></div>
</div>
<div class="sendBox">
<textarea class="sendInfo"></textarea>
<button onclick="send()">发送</button>
</div>
</body>
<div class="firstStep">
<div class="firstName">
<input type="text" class="username" name="username"
placeholder="给自己取一个响亮的名字!" /><input type="button" class="btn"
onclick="nameok()" value="进入聊天" />
</div>
</div>
</html>
- 聊天web项目
- web版即时聊天
- 怎么实现Web聊天
- web 聊天研究
- 即时聊天web即时通讯
- JAVA项目1:聊天
- 局域网LanQQ聊天项目
- 局域网聊天项目
- 在WEB项目中调用QQ通讯组件打开QQ聊天界面
- 手机web页面调用打开QQ聊天功能(个人项目经验)
- 前端百科---Web聊天排版
- Web聊天窗口提示框
- 漂亮的WEB桌面+WEB聊天系统
- Silverlight视频语音聊天项目
- ionic 在线聊天项目模板
- 仿QQ聊天项目(二)
- 开源项目--蓝牙聊天
- 开源项目--蓝牙聊天
- NDK的基础教程 一 最简单的NDK使用
- PAT 1123. Is It a Complete AVL Tree (30)
- 使用VS Code进行C语言学习
- link和@import的区别
- Spring所遵循的发布版本命名规则
- 聊天web项目
- Python 基础 ——异常与错误处理
- easyUI 动态生成表头,与动态绑定数据,实现代码
- Tomcat
- Calendar的应用
- jar
- 哪有简明python教程下载?
- Android BroadcastReceiver之监听外置SD卡状态
- C# 打印图形 集合