基于python面向对象多人聊天室

1、项目环境

项目名称:多人聊天室
项目模式:C/S
开发环境:win10+python3.8+pycharm
所需知识:python GUI编程,多线程编程,网络编程,数据库编程

2、流程


3、程序设计

了解一下服务器扮演的角色,下面是服务器的业务流程。大致工作模式
服务器:

客户端:

  • 首先服务器在指定的端口进行监听,等待客户的链接
  • 客户端链接到服务器之后,服务器开启单线程来处理该用户的请求
  • 处理线程等待客户端发送的请求
  • 服务器根据客户端请求类型的不同,调用不同处理的函数
  • 处理完客户端请求之后,再次回到第三步继续等待处理客户端新的请求
  • 客户端退出登录,服务器也会关闭对客户端的处理线程,释放资源

4、响应协议设计

  • 我们都知道三次握手和四次挥手,这里呢我们约定了客户端发送什么样格式的数据给服务器,服务器又需要返回什么样格式的数据给客户端,客户端会有不同的请求,所以我们针对不同的请求个响应定义了需求个相应号,来区分不同的请求和响应

  • 网络上一般使用json和xml格式来传输数据,但是用他们来传输,对于我们的项目有点复杂,我们的项目没有这么复杂的数据,我们采用|进行分割,然后拿到数据进行split一下就可以了。

  • 登录响应格式: 1001|ret|nickname|username,其中ret
    代表服务器端验证的结果,如果是0,表示服务端验证失败,后面的nickname username
    会为空字符串,若是1 ,表示服务端验证成功,nickname 为服务端返回的该用户的昵称,username 是该用户的用户名。

  • 聊天的响应格式:1002|nickname|message, nicakname 是为聊天信息发送者的昵称,message
    是发送的聊天信息

    下面我们定义了服务端需要的一些常量,以及为了实现客户端和服务端通信定义的一些协议编号,协议编号如下:

#----数据协议相关配置----
REQUEST_LOGIN = '0001' #登陆请求
REQUEST_CHAT= '0002' #聊天请求
RESPONSE_LOGIN_RESULT = '1001' #登陆结果响应
RESPONSE_CHAT= '1002' #聊天响应
DELIMITER = '|' #自定义协议数据分割符
SERVER_IP = '127.0.0.1' #服务器地址
SERVER_PORT = 8090 #服务器端口

5、面向对象的思想

服务器、客户端分离设计内容:

6、服务器通讯实现

  1. 制作协议报头,响应数据,制定一个模块config.py
#----数据协议相关配置----
REQUEST_LOGIN = '0001' #登陆请求
REQUEST_CHAT= '0002' #聊天请求
RESPONSE_LOGIN_RESULT = '1001' #登陆结果响应
RESPONSE_CHAT= '1002' #聊天响应
DELIMITER = '|' #自定义协议数据分割符
SERVER_IP = '127.0.0.1' #服务器地址
SERVER_PORT = 8090 #服务器端口#----数据库相关配置----   #具体参数自己设置
DB_HOST='127.0.0.1'#这里是你数据库IP地址
DB_PORT=3306       #这里是你数据库端口
DB_NAME='py_chat'  #这里是你数据库名
DB_USER='root'     #这里是你数据库登陆账号
DB_PASSWD='123456' #这里是你数据库密码
CHARSET='utf-8'
  1. 处理服务器响应字符串的拼接,制定一个模块response_protocol.py
from config import *class ResponseProtocol (object):"""服务器响应协议的格式字符串处理"""@staticmethoddef response_login_result(result: str, nickname: str, username: str) -> str:"""拼接登陆响应:param result:登陆结果,0或则1,0标识登陆失败,1标识登陆成功:param nickname:登陆名,登陆失败,该值为空字符串:param username:登陆ID,登陆失败,该值为空字符串:return 登陆结果相应格式字符串"""return DELIMITER.join ([RESPONSE_LOGIN_RESULT, result, nickname, username])@staticmethoddef response_chat(nickname, messages):"""拼接聊天相应,数据格式为:“相应协议编号|聊天发送者昵称|聊天信息”:param nickname: 聊天内容发送者昵称:param messages: 聊天内容:return: 聊天相应协议格式字符串"""return DELIMITER.join([RESPONSE_CHAT, nickname, messages])

7、主体框架搭建

基本逻辑业务-服务端
server.py 模块定义Server类来处理服务器业务逻辑,该类实现了服务器的主体框架

from server_socket import ServerSoket
from socket_warpper import SocketWrapper
from threading import Thread
from config import *
from response_protocol import *
from dbHandle import DBHandleclass Server(object):"""自定义套接字,负责初始化服务器套接字需要的相关参数"""def __init__(self):# 初始化套结字self.server_socket = ServerSoket()# 创建请求的ID和方法关联字典self.requset_handle_function = {}self.register(REQUEST_LOGIN, self.request_login_handle)self.register(REQUEST_CHAT, self.request_chat_handle)# 创建保存当前登录用户字典self.clients = {}self.db = DBHandle()'''注册消息类型和处理函数到字典'''def register(self, requeset_id, handle_function):self.requset_handle_function[requeset_id] = handle_function'''启动程序'''def startup(self):"""启动器"""while True:print('正在等待客户端连接')soc, addr = self.server_socket.accept()# print ('获取到客户端连接')client_soc = SocketWrapper(soc)# 启动线程处理该用户请求Thread(target=lambda: self.request_handle(client_soc)).start()'''处理客户端数据'''def request_handle(self, client_soc):while True:# 接收客户端数据recv_data = client_soc.recv_data()if not recv_data:# 没有接收到数据客户端应该已经关闭self.remve_offline_user(client_soc)client_soc.close()break'''解析数据'''parse_data = self.parse_request_text(recv_data)'''分析请求类型,并依据请求类型调用相应的分类处理''''''# 获得使用的方法名 方法名 = 字典[value]  注: 如 字典[key]可以互相找到字典[value]# 此处 字典[key]=0001 对应得字典[value] = REQUEST_LOGIN#例子:parse_data = '0001|XXX|XXX'parse_data['requset_id'] = ‘0001’requset_handle_function['0001'] = self.request_login_handlehandle_funtion = self.request_login_handle'''handle_funtion = self.requset_handle_function.get(parse_data['requset_id'])if handle_funtion:# 按照方法名调用方法handle_funtion(client_soc, parse_data)else:# 如果传输内容不匹配,返回错误请求self.request_err_handle(client_soc)'''用户离线操作'''def remve_offline_user(self, client_soc):for username, info in self.clients.items():if info['sock'] == client_soc:print(self.clients[username]['nickname'] + '已经离开')del self.clients[username]break'''解析客户端发送来的数据''''''解析数据内容'''def parse_request_text(self, recv_data):'''登录信息登录信息:0001|username|password聊天信息:0002|username|messages错误信息:err'''print('解析客户端数据:' + recv_data)requset_list = recv_data.split(DELIMITER)requset_data = {}requset_data['requset_id'] = requset_list[0]if requset_data['requset_id'] == REQUEST_LOGIN:requset_data['username'] = requset_list[1]requset_data['password'] = requset_list[2]elif requset_data['requset_id'] == REQUEST_CHAT:requset_data['username'] = requset_list[1]requset_data['messages'] = requset_list[2]return requset_data'''登录处理'''def request_login_handle(self, client_sock, requet_data):# print('收到登录请求')username = requet_data['username']password = requet_data['password']# 查询用户是否合法ret, nickname, username = self.check_user_login(username, password)# 如果登录成功,则保存用户连接套接字if ret == '1':self.clients[username] = {'sock': client_sock, 'nickname': nickname}# 组装响应结果response_text = ResponseProtocol.response_login_result(ret, nickname, username)# 发送响应结果client_sock.send_data(response_text)'''聊天处理'''def request_chat_handle(self, client_sock, requet_data):# 获取消息内容username = requet_data['username']messages = requet_data['messages']try:nickname = self.clients[username]['nickname']except:client_sock.send_data('您未登录,请登录后再发消息')return# 拼接发送给客户的消息文本msg = ResponseProtocol.response_chat(nickname, messages)# 转发消息给在线用户for u_name, info in self.clients.items():if username == u_name:continueinfo['sock'].send_data(msg)print(msg)'''错误信息处理'''def request_err_handle(self, client_sock):print("传输数据出错------")client_sock.send_data('数据无效,请重新确认')'''检查用户是否登录成功,返回检查结果(0/失败,1/成功,昵称,用户账号'''def check_user_login(self, username, password):# print("正在检测是否成功")# 从数据库查询用户信息sql = "select * from users where username = '%s' " % usernameresult = self.db.get_one(sql)# 如果没有查询结果,用户不存在,登录失败if not result:# print("用户不存在,登录失败")return '-1', ' ', username# 密码不匹配,说明密码错误,登录失败if password != result["password"]:# print("密码错误,登录失败")return '0', ' ', username# 登录成功# print("验证正确,登录成功")print(result['nickname'] + "进入聊天室")return '1', result['nickname'], usernameif __name__ == '__main__':Server().startup()
  • 这里我们自定义一个套接字,让类继承socket、super找父类的套接字有一个初始化,不初始化的类型告诉他
import socket
import configclass ServerSoket(socket.socket):"""自定义套接字,负责初始化服务器套接字需要的相关参数"""def __init__(self ):#设置TCP类型#初始化套结字super(ServerSoket,self).__init__(socket.AF_INET,socket.SOCK_STREAM)self.bind((config.SERVER_IP,config.SERVER_PORT))#设置为监听模式self.listen(128)

super(ServerSocket,self).init(socket.AF_INET,socket.SOCK_STREAM),绑定地址和端口,这里的参数不能写死,因为你要是写死,以后你要改代码要找一大堆的代码,这里我们把它固定在config.py 里面,以后要想改直接到配置相关项去改。

  • 初始化服务器套接字需要的相关操作。
from server_socket import ServerSocket
from socket_wrapper import SocketWrapper
from threading import Thread
class Server(object):"""服务器的核心类"""def __init__(self):# 初始化套结字self.server_socket = ServerSoket()# 创建请求的ID和方法关联字典self.requset_handle_function = {}self.register(REQUEST_LOGIN, self.request_login_handle)self.register(REQUEST_CHAT, self.request_chat_handle)# 创建保存当前登录用户字典self.clients = {}self.db = DBHandle()def startup(self):"""启动器"""while True:print('正在等待客户端连接')soc, addr = self.server_socket.accept()# print ('获取到客户端连接')client_soc = SocketWrapper(soc)# 启动线程处理该用户请求Thread(target=lambda: self.request_handle(client_soc)).start()

首先在__ init__ 方法里创建监听的套接字,当我们调用start方法启动服务器程序,在该函数中我们使用while来获取客户端的连接,有客户连接到服务器,服务器会获取一个套接字来标识与该客户的连接,然后我们开启新的线程来处理客户端的连接,该线程函数为Server类中的request_handle方法,该方法接收套接字作为参数,request_handle 方法是服务端请求处理的核心方法

8、消息处理request_handle 的处理

接收–>解析–>判断–>处理

def __init__(self):# 初始化套结字self.server_socket = ServerSoket()# 创建请求的ID和方法关联字典self.requset_handle_function = {}self.register(REQUEST_LOGIN, self.request_login_handle)self.register(REQUEST_CHAT, self.request_chat_handle)# 创建保存当前登录用户字典self.clients = {}def register(self, requeset_id, handle_function):'''注册消息类型和处理函数到字典'''self.requset_handle_function[requeset_id] = handle_functiondef request_handle(self, client_soc):'''处理客户端数据'''while True:# 接收客户端数据recv_data = client_soc.recv_data()if not recv_data:# 没有接收到数据客户端应该已经关闭self.remve_offline_user(client_soc)client_soc.close()break'''解析数据'''parse_data = self.parse_request_text(recv_data)'''分析请求类型,并依据请求类型调用相应的分类处理''''''# 获得使用的方法名 方法名 = 字典[value]  注: 如 字典[key]可以互相找到字典[value]# 此处 字典[key]=0001 对应得字典[value] = REQUEST_LOGIN#例子:parse_data = '0001|XXX|XXX'parse_data['requset_id'] = ‘0001’requset_handle_function['0001'] = self.request_login_handlehandle_funtion = self.request_login_handle'''handle_funtion = self.requset_handle_function.get(parse_data['requset_id'])if handle_funtion:# 按照方法名调用方法handle_funtion(client_soc, parse_data)else:# 如果传输内容不匹配,返回错误请求self.request_err_handle(client_soc)
  • 我们接受到客户的数据之后看它发来的数据类型是什么,调用相应的处理函数,这里的id类型和方法是唯一的,我们只需要初始化一次就可以,在init初始化。在后面我们不可能只有发送信息的功能,可能还有图片,视频等等在初始化里面加功能id就可以,来梳理思路:假如发送的消息是0001|uu|11111
    调用 parse_request_text,按照类型分析数据 ,发现id=0001,返回 request_data
    ,分析请求类型,调用相应的处理函数 ,调用 request_handle_function, 发现请求的id在里面,开始调用登录功能。

9、登录和聊天功能的处理

  • 获取登录的用户名和密码
  • 查询数据,是否存在对应的用户
  • 如果登录成功,保存用户信息,失败什么都不做
  • 返回登录结果给客户端
'''登录处理'''def request_login_handle(self, client_sock, requet_data):# print('收到登录请求')username = requet_data['username']password = requet_data['password']# 查询用户是否合法ret, nickname, username = self.check_user_login(username, password)# 如果登录成功,则保存用户连接套接字if ret == '1':self.clients[username] = {'sock': client_sock, 'nickname': nickname}# 组装响应结果response_text = ResponseProtocol.response_login_result(ret, nickname, username)# 发送响应结果client_sock.send_data(response_text)
'''聊天处理'''def request_chat_handle(self, client_sock, requet_data):# 获取消息内容username = requet_data['username']messages = requet_data['messages']try:nickname = self.clients[username]['nickname']except:client_sock.send_data('您未登录,请登录后再发消息')return# 拼接发送给客户的消息文本msg = ResponseProtocol.response_chat(nickname, messages)# 转发消息给在线用户for u_name, info in self.clients.items():if username == u_name:continueinfo['sock'].send_data(msg)print(msg)
'''检查用户是否登录成功,返回检查结果(0/失败,1/成功,昵称,用户账号'''def check_user_login(self, username, password):# print("正在检测是否成功")# 从数据库查询用户信息sql = "select * from users where username = '%s' " % usernameresult = self.db.get_one(sql)# 如果没有查询结果,用户不存在,登录失败if not result:# print("用户不存在,登录失败")return '-1', ' ', username# 密码不匹配,说明密码错误,登录失败if password != result["password"]:# print("密码错误,登录失败")return '0', ' ', username# 登录成功# print("验证正确,登录成功")print(result['nickname'] + "进入聊天室")return '1', result['nickname'], username

10、数据库的处理

  • 新建dbHandle.py
from  pymysql import connect
from  config import  *class DBHandle(object):'''mysql管理器'''def __init__(self):'''初始化数据库'''self.conn= connect(host=DB_HOST,port=DB_PORT,database=DB_NAME,user=DB_USER,password=DB_PASSWD)self.cursor = self.conn.cursor()# 释放数据库资源def close_db(self):self.cursor.close()self.conn.close()def get_one(self, sql):#执行SQL结果self.cursor.execute(sql)#获取查询结果query_result = self.cursor.fetchone()#判断是否有结果if not query_result:return None#获得字段名称列表fileds = [filed[0] for filed in self.cursor.description]#保存返回结果return_data = {}for filed, value in zip(fileds, query_result):return_data[filed] = value#查询结果return return_data
  • 清理离线的用户
 '''用户离线操作'''def remve_offline_user(self, client_soc):for username, info in self.clients.items():if info['sock'] == client_soc:print(self.clients[username]['nickname'] + '已经离开')del self.clients[username]break
  • 聊天功能处理:通过服务器向每一个登录在线的人转发消息,不需要向自己发消息
    ‘’‘聊天处理’’’
 def request_chat_handle(self, client_sock, requet_data):# 获取消息内容username = requet_data['username']messages = requet_data['messages']try:nickname = self.clients[username]['nickname']except:client_sock.send_data('您未登录,请登录后再发消息')return# 拼接发送给客户的消息文本msg = ResponseProtocol.response_chat(nickname, messages)# 转发消息给在线用户for u_name, info in self.clients.items():if username == u_name:continueinfo['sock'].send_data(msg)print(msg)

11、客户端实现

客户端采用GUI视图来写
登录窗口显示
新建项目 Client
新建win_client.py

from tkinter import Tk
from tkinter import Label,Entry,Frame,Button,LEFT,ENDclass WindowLogin (Tk):"""登陆窗口"""def __init__(self):super (WindowLogin, self).__init__ ()# 设置窗口属性self.window_init ()# 填充控件self.add_widgets ()# self.on_reset_button_click (lambda :print(self.get_username()))# self.on_login_button_click (lambda: print(self.get_password()))"""初始化窗口属性"""def window_init(self):#设置窗口标题self.title('登陆窗口')#设置窗口不能被拉伸self.resizable  (False,False)#获取窗口的位置变量window_width = 255window_height =100screenWidth = self.winfo_screenwidth()screenHeight = self.winfo_screenheight()pos_x = (screenWidth-window_width)/2pos_y = (screenHeight-window_height)/2#设置窗口大小和位置self.geometry('%dx%d+%d+%d' % (window_width,window_height,pos_x,pos_y))"""添加控件到窗口"""def add_widgets(self):"""添加控件到窗口"""# 用户名提示标签username_label = Label (self)username_label['text'] = '用户名:'username_label.grid (row=0, column=0, padx=10, pady=5)# 用户名输入文本框username_entry = Entry (self, name='username_entry')username_entry['width'] = 20username_entry.grid (row=0, column=1, padx=10, pady=5)# 密码提示标签password_label = Label (self)password_label['text'] = '密 码:'password_label.grid (row=1, column=0)# 密码输入文本框password_entry = Entry (self, name='password_entry')password_entry['show'] = '*'username_entry['width'] = 20password_entry.grid (row=1, column=1)# 按钮区button_frame = Frame (self, name='button_frame')# 重置按钮reset_button = Button (button_frame, name='reset_button')reset_button['text'] = '重置'reset_button.pack (side=LEFT, padx=40)# 登录按钮login_button = Button (button_frame, name='login_button')login_button['text'] = '登录'login_button.pack (side=LEFT)button_frame.grid (row=2, columnspan=2, pady=5)def get_username(self):"""获取用户名"""return self.children['username_entry'].get ()def get_password(self):"""获取密码"""return self.children['password_entry'].get ()def clear_username(self):""" 清空用户名"""return self.children['username_entry'].delete (0, END)def clear_password(self):""" 清空用户名"""return self.children['password_entry'].delete (0, END)def on_reset_button_click(self, command):"""重置按钮的响应注册"""reset_button = self.children['button_frame'].children['reset_button']reset_button['command'] = commanddef on_login_button_click(self, command):"""登录按钮的响应注册"""login_button = self.children['button_frame'].children['login_button']login_button['command'] = command  # 把command函数赋值给登录按钮的command,点击时调用commanddef on_window_close(self, command):"""关闭窗口的响应注册"""self.protocol ('WM_DELETE_WINDOW', command)
  • 整体采用了grid表格的布局,其中用户名标签放置在(1,1)第一行第一列位置,对应的用户名的输入放置在(1,2),密码标签放置在(2,1),密码的输入放置在(2,2),重置和登录按钮放置在第三行居中的位置。
  • 由于我们已经全局使用了grid表格布局,所有我们将他们放在一个Frame里面,两个按钮在Frame中水平布局
    再将Frame整体放置在窗口的第三行,并占据两列。

12、客户端通讯实现

通讯模块

  1. 制作协议报头,响应数据,创建一个模块config.py
#----数据协议相关配置----
REQUEST_LOGIN = '0001' #登陆请求
REQUEST_CHAT= '0002' #聊天请求
RESPONSE_LOGIN_RESULT = '1001' #登陆结果响应
RESPONSE_CHAT= '1002' #聊天响应
DELIMITER = '|' #自定义协议数据分割符
SERVER_IP = '127.0.0.1' #服务器地址
SERVER_PORT = 8090 #服务器端口
CHARSET='utf-8'
  1. 处理服务器响应字符串的拼接,制定一个模块request_protocol.py

from config import *class RequestProtocol (object):"""服务器响应协议的格式字符串处理"""@staticmethoddef request_login_result(username,password):"""拼接登陆响应:param username:登陆用户名,登陆失败,该值为空字符串:param password:登陆密码:return 登陆结果相应格式字符串"""return DELIMITER.join ([REQUEST_LOGIN,username, password])@staticmethoddef request_chat(username, messages):"""拼接聊天相应,数据格式为:“相应协议编号|聊天发送者账号|聊天信息”:param REQUEST_CHAT::param username: 聊天内容发送者账号:param messages: 聊天内容:return: 聊天相应协议格式字符串"""return DELIMITER.join ([REQUEST_CHAT, username, messages])

13、客户端业务实现

新建模块client.py

   from request_protocol import RequestProtocol
from window_login import WindowLogin
from client_socket import ClientSocket
from threading import Thread
from config import *
from tkinter.messagebox import  showinfoclass Client(object):def __init__(self):"""初始化客户端资源"""# 初始化登陆窗口self.window = WindowLogin()self.window.on_login_button_click(self.send_login_data)self.window.on_reset_button_click(self.clear_inputs)# 创建客户端套接字self.conn = ClientSocket()# 初始化消息处理函数self.response_handle_funtion = {}self.regist(RESPONSE_LOGIN_RESULT, self.response_login_handle)self.regist(RESPONSE_CHAT, self.response_chat_handle)def regist(self, requeset_id, handle_function):"""注册消息和消息对应的方法到字典里"""self.response_handle_funtion[requeset_id] = handle_functiondef startup(self):'''开启窗口'''self.conn.connect()Thread(target=self.response_handle).start()self.window.mainloop()def clear_inputs(self):"""清空窗口内容"""self.window.clear_password()self.window.clear_username()def send_login_data(self):username = self.window.get_username()password = self.window.get_password()request_text = RequestProtocol.request_login_result(username, password)self.conn.send_data(request_text)def response_handle(self):"不断收发服务器消息"while True:recv_data = self.conn.recv_data()print('收到服务器消息:' + recv_data)response_data = self.parse_response_data(recv_data)# 根据事件类型,调用指定方法名handle_funtionn = self.response_handle_funtion[response_data['response_id']]if handle_funtionn:handle_funtionn(response_data)@staticmethoddef parse_response_data(recv_data):'''登陆响应消息:1001|成功/失败|昵称|账号聊天响应消息:1002|发送者昵称|消息内容'''# 使用协议约定的符号来切割消息response_data_list = recv_data.split(DELIMITER)# 解析消息的各个组成部分response_data = {}response_data['response_id'] = response_data_list[0]if response_data['response_id'] == RESPONSE_LOGIN_RESULT:response_data['result'] = response_data_list[1]response_data['nickname'] = response_data_list[2]response_data['username'] = response_data_list[3]elif response_data['response_id'] == RESPONSE_CHAT:response_data['nickname'] = response_data_list[1]response_data['message'] = response_data_list[2]return response_datadef response_chat_handle(self, response_data):print('接收到聊天消息~', response_data)def response_login_handle(self, response_data):result = response_data['result']if result !='1':showinfo('提示','账号或密码错误')returnnickname = response_data['nickname']username = response_data['username']print('%s 的昵称为 %s ,已经登录聊天室' % (username,nickname))

基于python面向对象多人聊天室相关推荐

  1. 基于Python的多人聊天室的设计与实现

    基于Python的多人聊天室的设计与实现 摘要  本文介绍了基于即时通讯的Python实现web版多人聊天室的设计和实现.这个系统利用了多种先进的技术,如Django.Channels.WebSock ...

  2. 【Linux网络编程】基于UDP实现多人聊天室

    文章目录 一.UDP的概念 1.1 UDP 1.2 UDP特点 二. 采用UDP实现多人聊天室原因 三.多人聊天室项目功能 四.实现多人聊天室项目流程分析 4.1 前期准备 4.1.1 定义结构体 4 ...

  3. linux多人聊天室 qt,Qt编程详解--网络通信之基于TCP的多人聊天室

    一.了解TCP的通信过程 Qt中封装了TCP协议 QTcpServer类负责服务端: 1.创建QTcpServer对象 2.监听listen需要的参数是地址和端口号 3.当有新的客户端连接成功时会发射 ...

  4. 多人聊天功能代码php,基于swoole实现多人聊天室

    本文实例为大家分享了swoole创建多人多房间聊天室的具体代码,供大家参考,具体内容如下 核心的swoole代码 基本的cs(client-sercer)结构不变,这里利用的是redis的哈希和set ...

  5. Java NIO基于控制台的多人聊天室

    闲来无事写了个基于NIO的聊天室项目,费话不说了,直接贴代码吧. Server端代码如下: package com.xz.helloworld.nettyt.nio.im;import java.io ...

  6. vc udp 广播接收和发送_udp聊天?使用udp+python实现多人聊天室

    信来到这个文章里面的朋友不会对udp陌生,话不多说直接开始. 由于udp没有建立连接,也没有实际上的客户端和服务器端. 但是我们需要让一个udp来充当服务器!实现消息广播从而达到聊天室的效果. 以下是 ...

  7. python socket 多人聊天室

    参考来源(其实我从上面复制了一点): Python 的 Socket 编程教程  http://www.oschina.net/question/12_76126 Python线程指南 http:// ...

  8. php 多人聊天室,基于swoole实现多人聊天室,聊天室实现

    namespace app\common;require_once 'Predis.php';require_once 'Task.php';/** * socket面向对象的编译*/ classWs ...

  9. 基于udp的多人聊天室

    服务端 相当于一个服务器,接收用户发送的过来的消息(登录消息,文本消息,退出登录消息),然后将其转发给其用户. 基本功能: 1.把新注册用户登陆消息告诉其它用户 2.把新用户插入到用户链表中 3.服务 ...

最新文章

  1. STM32如何计算RTC时钟异步预分频和同步预分频
  2. sample, batch, epoch 分别是什么?
  3. spring hibernate 连接sqlserver 数据库的时候还需要jdbc包吗?
  4. Ubuntu、CentOS 解决docker命令权限问题(sudo)
  5. 如何更改Twitter Bootstrap模式框的默认宽度?
  6. (转载)解决macOS /usr/include 无法写入或者不存在的问题
  7. 【hdoj_1398】SquareCoins(母函数)
  8. [ios] 微信订阅号: ios博文精选
  9. python时间计算_python datetime库使用和时间加减计算
  10. js datagrid新增一行_Django接口新增页面编写_2(十五)
  11. Linux学习总结(28)——Linux主机加固
  12. Python 基础—— operator 模块、functools
  13. numpy 用于图像处理(灰度图、转置、通道分离、图像扩展、水平镜像、水平翻转、调换x,y坐标、添加mask、随机打乱顺序、交换通道)
  14. ie浏览器当前的安全设置使计算机面临风险,IE安全设置
  15. 【SSD目标检测】3:训练自己的数据集
  16. 孪生支持向量机基本原理
  17. dz搬家 win linux,Discuz论坛完美搬家 详细分享我的DZ搬家步骤
  18. 安卓模拟位置之夜神模拟器
  19. intel无线网络管理服务器,配置Intel无线网卡连接到管理帧保护(MFP) -启用网络
  20. Web前端和Web后端的区分

热门文章

  1. get请求报错400状态码
  2. 博客园自定义博客侧边栏公告的过滤漏洞
  3. c语言里面gets(a)是什么意思,C语言中的gets()函数
  4. miui 系统组件 功能提示
  5. CTFshow菜鸡杯WP
  6. 拼多多新阶段,透露出不寻常
  7. 多态在android中(利用接口调用服务中方法)的应用
  8. 蓝牙定位与UWB定位的对比
  9. YApi pro使用教程,超好用新手上路
  10. 做好这四点,职业规划很容易!