Python+Socket实现多人聊天室,功能:好友聊天、群聊、图片、表情、文件等

news2024/11/26 2:27:12

一、项目简介

本项目主要基于python实现的多人聊天室,主要的功能如下:

  • 登录注册
  • 添加好友
  • 与好友进行私聊
  • 创建群聊
  • 邀请/申请加入群聊
  • 聊天发送图片
  • 聊天发送表情
  • 聊天发送文件
  • 聊天记录保存在本地中
  • 聊天过程中发送的文件保存本地

二、环境介绍

  • python3.8
  • mysql8.0
  • tkinter:作为程序的gui库
  • flask :主要用于登录/注册、表情下载、信息修改等http请求等
  • socket:主要用户聊天过程中消息发送、对方在线状态更新等
  • pygame:用于播放新消息提示音

三、运行展示

登录:
登录页面
注册:
image-20220427221842887
登录后主界面:
image-20220427221858349
点击右上方“修改资料”:
image-20220427221942224
添加好友或群:
image-20220427222002416
双击好友或群打开聊天窗口:
image-20220427222032094
点击表情按钮选择发送的表情:
image-20220427222102584
发送图片可以预览,点击文件名称直接打开:
image-20220427222217499

四、关键代码

配置文件:server.conf

配置服务器ip、http端口、socket端口、数据库的账号密码、是否启用新消息提示音

[server]
SERVER_IP = 127.0.0.1
HTTP_PORT = 8000
SOCKET_PORT = 8001
SQLALCHEMY_DATABASE_URI = mysql://root:root@127.0.0.1:3306/chatdb
ENABLE_MUSIC = 0

服务端主要代码:ChatServer.py

维持Socket通信、开启Flask进行http

# controller定义
@app.route('/login', methods=['POST'])
def login():
    try:
        params = request.values
        login_name = params['loginName']
        pwd = params['pwd']
        md5 = hashlib.md5()
        md5.update(pwd.encode(encoding='utf-8'))
        password = md5.hexdigest()

        users = Users.query.filter(Users.loginName == login_name)\
            .filter(Users.pwd == password).all()
        if len(users) == 0:
            return Result.fail('账号不存在或密码错误')
        else:
            # 服务返回uid,客户端打开好友界面后,凭借此uid与服务器进行socket连接
            uid = users[0].id
            # 已存在uid:已登录,重新登录,原登录退出连接,退出程序
            if uid in online_users.keys():
                # logout
                connection = online_users[int(uid)]
                send_msg = {'type': UtilsAndConfig.SYSTEM_LOGOUT}
                connection.send(json.dumps(send_msg).encode())
            online_users[uid] = None

            return Result.success(uid)
    except Exception as e:
        return Result.fail('参数异常')

# 监听socket
def socket_listen_thread():
    while True:
        connection, address = mySocket.accept()
        # 用户连接携带的uid,判断是否和服务器相同
        data_dic = json.loads(connection.recv(1024).decode())

        uid = None
        if data_dic['type'] == UtilsAndConfig.CONNECTION_REQUEST:
            uid = int(data_dic['uid'])
        else:
            connection.send(UtilsAndConfig.CONNECTION_NOT_ALLOWED.encode())
        if uid in online_users.keys():
            # 可建立连接
            online_users[uid] = connection
            connection.send(UtilsAndConfig.CONNECTION_ALLOWED.encode())

            # 通知好友们,我上线了
            friends = get_friends_by_uid(uid)
            for f in friends:
                if f.id in online_users.keys():
                    friend_connection = online_users[f.id]
                    send_msg = {'type': UtilsAndConfig.FRIENDS_ONLINE_CHANGED, 'uid': uid, 'online': 1}
                    friend_connection.send(json.dumps(send_msg).encode())

            # 创建子线程,保持通信
            keep_link_thread = threading.Thread(target=socket_keep_link_thread, args=(connection, ))
            keep_link_thread.setDaemon(True)
            keep_link_thread.start()
        else:
            connection.send(UtilsAndConfig.CONNECTION_NOT_ALLOWED.encode())


def socket_keep_link_thread(connection):
    while True:
        try:
            msg = connection.recv(1024).decode()
            if not msg:
                if connection in online_users.values():
                    uid = list(online_users.keys())[list(online_users.values()).index(connection)]
                    online_users.pop(uid)
                    friends = get_friends_by_uid(uid)
                    for f in friends:
                        if f.id in online_users.keys():
                            friend_connection = online_users[f.id]
                            send_msg = {'type': UtilsAndConfig.FRIENDS_ONLINE_CHANGED, 'uid': uid, 'online': 0}
                            friend_connection.send(json.dumps(send_msg).encode())
                    connection.close()
                return
            else:
                msg_json = json.loads(str(msg))
                # 发消息
                if msg_json['type'] == UtilsAndConfig.CHAT_SEND_MSG:
                    to_id = msg_json['toId']
                    is_friend = msg_json['isFriend']
                    from_uid = msg_json['fromId']
                    send_time = msg_json['sendTime']
                    msg_text = msg_json['msgText']

                    data = {'from_uid': from_uid, 'to_id': to_id, 'send_time': send_time, 'msg_text': msg_text,
                            'is_friend': is_friend, 'type': '', 'msg_type': 'train'}
                    # 通知接收方,收到新消息
                    if is_friend == 1:
                        if to_id in online_users.keys():
                            friend_connection = online_users[to_id]
                            data['type'] = UtilsAndConfig.CHAT_HAS_NEW_MSG
                            friend_connection.send(json.dumps(data).encode())

                            # 通知发送方,发送成功
                            data['type'] = UtilsAndConfig.CHAT_SEND_MSG_SUCCESS
                            connection.send(json.dumps(data).encode())
                        else:
                            # 通知发送方,发送失败,对方不在线
                            data['type'] = UtilsAndConfig.CHAT_SEND_MSG_ERR
                            connection.send(json.dumps(data).encode())
                    else:
                        # 群
                        members = get_group_members(to_id)
                        members_online = False
                        for m in members:
                            if m.uId in online_users.keys() and m.uId != from_uid:
                                members_online = True
                                member_connection = online_users[m.uId]
                                data['type'] = UtilsAndConfig.CHAT_HAS_NEW_MSG
                                member_connection.send(json.dumps(data).encode())
                        if members_online:
                            # 通知发送方,发送成功
                            data['type'] = UtilsAndConfig.CHAT_SEND_MSG_SUCCESS
                            connection.send(json.dumps(data).encode())
                        else:
                            # 通知发送方,发送失败,对方不在线
                            data['type'] = UtilsAndConfig.CHAT_SEND_MSG_ERR
                            connection.send(json.dumps(data).encode())
                if msg_json['type'] == UtilsAndConfig.CHAT_SEND_FILE:
                    from_id = msg_json['from_id']
                    to_id = msg_json['to_id']
                    is_friend = msg_json['is_friend']
                    send_date = msg_json['send_date']
                    file_length = msg_json['file_length']
                    file_suffix = msg_json['file_suffix']
                    file_name = msg_json['file_name']

                    file_save_name = str(uuid.uuid1()) + '.' + file_suffix
                    return_file_path = '/static/tmp/' + file_save_name
                    file_path = os.path.abspath(os.path.dirname(__file__)) + return_file_path
                    if not os.path.exists(os.path.dirname(file_path)):
                        os.makedirs(os.path.dirname(file_path))

                    data = {'from_uid': from_id, 'to_id': to_id, 'send_time': send_date, 'file_name': file_name,
                            'is_friend': is_friend, 'type': UtilsAndConfig.CHAT_SEND_FILE_SUCCESS,
                            'file_path': return_file_path}

                    if is_friend == 1:
                        if to_id not in online_users.keys():
                            # 通知发送方,发送失败,对方不在线
                            data['type'] = UtilsAndConfig.CHAT_SEND_MSG_ERR
                            connection.send(json.dumps(data).encode())
                            continue
                    else:
                        members = get_group_members(to_id)
                        flag = True
                        for m in members:
                            if m.uId in online_users.keys() and m.uId != from_id:
                                flag = False
                                break
                        if flag:
                            # 通知发送方,发送失败,对方不在线
                            data['type'] = UtilsAndConfig.CHAT_SEND_MSG_ERR
                            connection.send(json.dumps(data).encode())
                            continue

                    # 接收文件
                    total_data = b''
                    file_data = connection.recv(1024)
                    total_data += file_data
                    num = len(file_data)
                    while num < file_length:
                        file_data = connection.recv(1024)
                        num += len(file_data)
                        total_data += file_data

                    with open(file_path, "wb") as f:
                        f.write(total_data)

                    connection.send(json.dumps(data).encode())

                    # 通知接收方,收到新文件消息
                    if is_friend == 1:
                        friend_connection = online_users[to_id]
                        data['type'] = UtilsAndConfig.CHAT_HAS_NEW_FILE
                        friend_connection.send(json.dumps(data).encode())
                    else:
                        members = get_group_members(to_id)
                        for m in members:
                            if m.uId in online_users.keys() and m.uId != from_id:
                                member_connection = online_users[m.uId]
                                data['type'] = UtilsAndConfig.CHAT_HAS_NEW_FILE
                                member_connection.send(json.dumps(data).encode())

        except ConnectionAbortedError:
            if connection in online_users.values():
                uid = list(online_users.keys())[list(online_users.values()).index(connection)]
                online_users.pop(uid)
                friends = get_friends_by_uid(uid)
                for f in friends:
                    if f.id in online_users.keys():
                        friend_connection = online_users[f.id]
                        send_msg = {'type': UtilsAndConfig.FRIENDS_ONLINE_CHANGED, 'uid': uid, 'online': 0}
                        friend_connection.send(json.dumps(send_msg).encode())
                connection.close()
            return
        except ConnectionResetError:
            if connection in online_users.values():
                uid = list(online_users.keys())[list(online_users.values()).index(connection)]
                online_users.pop(uid)
                friends = get_friends_by_uid(uid)
                for f in friends:
                    if f.id in online_users.keys():
                        friend_connection = online_users[f.id]
                        send_msg = {'type': UtilsAndConfig.FRIENDS_ONLINE_CHANGED, 'uid': uid, 'online': 0}
                        friend_connection.send(json.dumps(send_msg).encode())
                connection.close()
            return


# 主线程
if __name__ == '__main__':
    # 启动socket线程
    socketThread = threading.Thread(target=socket_listen_thread)
    socketThread.setDaemon(True)
    socketThread.start()

    # 启动Flask服务器
    app.run(host=serverConfig.SERVER_IP, port=serverConfig.HTTP_PORT, debug=False)

客户端主界面:ChatHome.py

与服务器保持Socket通信、与服务端进行http交互

class ChatHome:
    def run(self):
        pygame.mixer.init()

        # Socket连接
        self.socket.connect((self.server_config.SERVER_IP, self.server_config.SOCKET_PORT))
        send_data = {'type': UtilsAndConfig.CONNECTION_REQUEST, 'uid': self.uid}
        self.socket.send(json.dumps(send_data).encode())
        socket_result = self.socket.recv(1024).decode()
        if socket_result != UtilsAndConfig.CONNECTION_ALLOWED:
            tkinter.messagebox.showwarning('提示', '参数出错,socket连接被拒绝!')
            sys.exit()

        # 创建子线程保持socket通信
        keep_link_thread = threading.Thread(target=self.socket_keep_link_thread)
        keep_link_thread.setDaemon(True)
        keep_link_thread.start()

        # 基本信息
        self.root = tk.Tk()
        self.root.title('ChatRoom')
        self.root.geometry('320x510+100+0')

        # 用户名
        self.frame_user_info = Frame(self.root, relief=RAISED, width=320, borderwidth=0, height=70, bg='#4F7DA4')
        self.frame_user_info.place(x=0, y=0)
        self.init_user_info()

        # 中间画布canvas
        self.frame_mid = Frame(self.root, width=320, height=340)
        self.frame_mid.place(x=0, y=70)
        # # 画布中的frame
        self.init_friends_and_group_view()
        # 下方按钮
        frame_bottom_button = Frame(self.root, relief=RAISED, borderwidth=0, width=320, height=50)
        frame_bottom_button.place(x=0, y=420)
        button_bottom_add_friends = Button(frame_bottom_button, width=11,
                                           text='加好友/加群', command=self.open_add_friends)
        button_bottom_add_friends.place(x=55, y=10)
        button_bottom_create_groups = Button(frame_bottom_button, width=11,
                                             text='创建群', command=self.open_create_groups)
        button_bottom_create_groups.place(x=165, y=10)

        # 新消息
        frame_message = Frame(self.root, relief=RAISED, borderwidth=0, width=320, height=50)
        frame_message.place(x=0, y=460)
        self.label_message_tip = Label(frame_message)
        self.label_message_tip.place(x=55, y=12)
        self.refresh_message_count()
        button_message_open = Button(frame_message, width=7,
                                     text='查看', command=self.open_message_window)
        button_message_open.place(x=193, y=10)
        self.root.mainloop()

    # 保持socket通信
    def socket_keep_link_thread(self):
        while True:
            try:
                back_msg = self.socket.recv(1024).decode()
                msg = json.loads(back_msg)
                # 好友状态改变
                if msg['type'] == UtilsAndConfig.FRIENDS_ONLINE_CHANGED:
                    self.frames_friend_view[msg['uid']].online_type_change(msg['online'])
                # 有新验证消息
                if msg['type'] == UtilsAndConfig.MESSAGE_NEW_MSG:
                    self.refresh_message_count()
                    self.play_new_msg_music()
                # 好友/群数量改变
                if msg['type'] == UtilsAndConfig.FRIENDS_GROUPS_COUNT_CHANGED:
                    self.init_friends_and_group_view()
                    self.refresh_message_count()
                # 有新文本消息, 写入缓存,更新显示
                if msg['type'] == UtilsAndConfig.CHAT_HAS_NEW_MSG:
                    from_uid = msg['from_uid']
                    to_id = msg['to_id']
                    is_friend = msg['is_friend']
                    txt = {'type': 'get', 'from_uid': from_uid, 'datetime': msg['send_time'],
                           'msg': msg['msg_text'], 'msg_type': 'train'}
                    UtilsAndConfig.add_one_chat_record(self.uid, is_friend, from_uid, to_id,
                                                       json.dumps(txt, cls=UtilsAndConfig.MyJSONEncoder,
                                                                  ensure_ascii=False), False)
                    # 是否打开聊天界面,打开则更新,未打开则好友列表提示新消息
                    if self.window_chat_context is not None and self.window_chat_context.to_id == from_uid\
                            and self.window_chat_context.is_friend == 1 and is_friend == 1:
                        self.window_chat_context.get_new_msg()
                        pass
                    elif self.window_chat_context is not None and self.window_chat_context.to_id == to_id\
                            and self.window_chat_context.is_friend == 0 and is_friend == 0:
                        self.window_chat_context.get_new_msg()
                    else:
                        if is_friend == 1:
                            self.frames_friend_view[from_uid].new_msg_comming()
                        else:
                            self.frames_group_view[to_id].new_msg_comming()
                    self.play_new_msg_music()
                # 发送文本消息成功, 写入本地缓存,更新显示
                if msg['type'] == UtilsAndConfig.CHAT_SEND_MSG_SUCCESS:
                    from_uid = msg['from_uid']
                    to_id = msg['to_id']
                    send_time = msg['send_time']
                    msg_text = msg['msg_text']
                    is_friend = msg['is_friend']
                    txt = {'type': 'send', 'datetime': send_time, 'msg': msg_text, 'msg_type': 'train'}
                    UtilsAndConfig.add_one_chat_record(self.uid, is_friend, from_uid, to_id,
                                                       json.dumps(txt, cls=UtilsAndConfig.MyJSONEncoder,
                                                                  ensure_ascii=False), True)
                    self.window_chat_context.get_new_msg()
                # 发送文件成功
                if msg['type'] == UtilsAndConfig.CHAT_SEND_FILE_SUCCESS:
                    to_id = msg['to_id']
                    send_time = msg['send_time']
                    file_name = msg['file_name']
                    is_friend = msg['is_friend']
                    txt = {'type': 'send', 'datetime': send_time, 'msg': file_name, 'msg_type': 'file'}
                    UtilsAndConfig.add_one_chat_record(self.uid, is_friend, self.uid, to_id,
                                                       json.dumps(txt, cls=UtilsAndConfig.MyJSONEncoder,
                                                                  ensure_ascii=False), True)
                    self.window_chat_context.get_new_msg()
                    self.window_chat_context.sending_file(False)
                # 收到文件
                if msg['type'] == UtilsAndConfig.CHAT_HAS_NEW_FILE:
                    to_id = msg['to_id']
                    from_uid = msg['from_uid']
                    send_time = msg['send_time']
                    file_name = msg['file_name']
                    is_friend = msg['is_friend']
                    file_path = msg['file_path']
                    files_dir = os.path.abspath(os.path.dirname(__file__)) + '/static/LocalCache/' \
                                + str(self.uid) + '/files/'
                    if not os.path.exists(os.path.dirname(files_dir)):
                        os.makedirs(os.path.dirname(files_dir))

                    all_file_name = file_name.split('/')[-1]
                    file_suffix = all_file_name.split('.')[-1]
                    end_index = len(all_file_name) - len(file_suffix) - 1
                    file_name = all_file_name[0:end_index]
                    file_save_path = files_dir + file_name + '.' + file_suffix
                    i = 1
                    while os.path.exists(file_save_path):
                        file_save_path = files_dir + file_name + '(' + str(i) + ')' + '.' + file_suffix
                        i += 1
                    # http下载文件,保存到本地
                    try:
                        url = self.server_config.HTTP_SERVER_ADDRESS + file_path
                        res = requests.get(url)
                        file_content = res.content
                        file = open(file_save_path, 'wb')
                        file.write(file_content)
                        file.close()
                    except requests.exceptions.InvalidSchema:
                        pass
                        # 服务器中文件不存在
                    txt = {'type': 'get', 'from_uid': from_uid, 'datetime': send_time,
                           'msg': file_save_path, 'msg_type': 'file'}
                    UtilsAndConfig.add_one_chat_record(self.uid, is_friend, from_uid, to_id,
                                                       json.dumps(txt, cls=UtilsAndConfig.MyJSONEncoder,
                                                                  ensure_ascii=False), False)

                    if self.window_chat_context is not None and self.window_chat_context.to_id == from_uid\
                            and self.window_chat_context.is_friend == 1 and is_friend == 1:
                        self.window_chat_context.get_new_msg()
                        pass
                    elif self.window_chat_context is not None and self.window_chat_context.to_id == to_id\
                            and self.window_chat_context.is_friend == 0 and is_friend == 0:
                        self.window_chat_context.get_new_msg()
                    else:
                        if is_friend == 1:
                            self.frames_friend_view[from_uid].new_msg_comming()
                        else:
                            self.frames_group_view[to_id].new_msg_comming()
                    self.play_new_msg_music()
                    # 告诉服务器 文件下载完成,可删除
                    url = self.server_config.HTTP_SERVER_ADDRESS + '/downloadFileSuccess?path=' + file_path
                    requests.get(url)
                # 发送聊天消息失败,不写入缓存,提示对方已下线
                if msg['type'] == UtilsAndConfig.CHAT_SEND_MSG_ERR:
                    tkinter.messagebox.showwarning('提示', '对方已下线,不能发送消息')
                # 服务器强制下线
                if msg['type'] == UtilsAndConfig.SYSTEM_LOGOUT:
                    self.socket.close()
                    tkinter.messagebox.showwarning('提示', '此账号已在别处登录!')
                    self.root.destroy()
                    return
            except ConnectionAbortedError:
                tkinter.messagebox.showwarning('提示', '与服务器断开连接!')
                self.root.destroy()
                return
            except ConnectionResetError:
                tkinter.messagebox.showwarning('提示', '与服务器断开连接!')
                self.root.destroy()
                return

五、私聊或评论告诉我,获取源码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/573977.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

浅谈 RISC-V 软件开发生态之 IDE

软件开发者是芯片公司非常重要的资产&#xff0c;CPU做出来是不够的&#xff0c;要让更多的软件开发者用这颗芯片才是成功。国际大厂们都有一只较大的软件团队&#xff0c;在做面向开发者的软件工具和SDK等。--张先轶博士&#xff1a;为什么RISC-V需要共建软件生态? 前言 目前…

VsCode终端无法使用conda切换环境的问题

一.问题描述: windows的cmd可以正常使用conda切换环境 为了方便想使用vscode的终端,但是报错: PS C:\Users\admin\Desktop\MyProject> conda activate objection1.8.4 CommandNotFoundError: Your shell has not been properly configured to use conda activate. invocati…

智能排班系统 【管理系统功能、操作说明——下篇】

文章目录 页面与功能展示排班日历月视图&#xff08;按职位查询&#xff09;月视图&#xff08;按员工查询&#xff09;周视图 排班任务管理创建排班计算任务设置任务的排班规则设置工作日客流量导入任务计算查看任务结果发布任务任务多算法计算 页面与功能展示 排班日历 在排…

vcruntime140.dll丢失的解决方法?教你如何修复好dll文件

Vcruntime140.dll文件是Windows操作系统中非常重要的一个动态链接库文件&#xff0c;用于支持使用Microsoft Visual C编译器创建的应用程序的运行。当Windows系统中的vcruntime140.dll文件丢失时&#xff0c;可能会导致某些应用程序无法正常启动。在尝试启动应用程序时&#xf…

Android HCE开发

我们来详细说明一下关于不同模式下的AID响应问题&#xff08;前提&#xff1a;一个手机&#xff0c;手机上有A、B两个HCE APP&#xff0c;通过读卡器向手机发送APDU选择指令&#xff09; 1、A和B的应用AID设置的都是payment模式&#xff0c; 只有手机当前选定的默认支付APP会响…

基于Faster rcnn pytorch的遥感图像检测

基于Faster rcnn pytorch的遥感图像检测 代码&#xff1a;https://github.com/jwyang/faster-rcnn.pytorch/tree/pytorch-1.0 数据集 使用RSOD遥感数据集&#xff0c;VOC的数据格式如下&#xff1a; RSOD是一个开放的目标检测数据集&#xff0c;用于遥感图像中的目标检测。…

图片类型转换,url,File,Base64,Blob

一&#xff0c;图片url转化为文件 function urlToFile(url, imageName) {return new Promise((resolve, reject) > {var blob nullvar xhr new XMLHttpRequest()xhr.open(GET, url)xhr.setRequestHeader(Accept, image/png)xhr.responseType blobxhr.onload () > {b…

JVM内存模型和结构详解

JVM内存模型和Java内存模型都是面试的热点问题&#xff0c;名字看感觉都差不多&#xff0c;实际上他们之间差别还是挺大的。 通俗点说&#xff0c;JVM内存结构是与JVM的内部存储结构相关&#xff0c;而Java内存模型是与多线程编程相关mikechen。 什么是JVM JVM是Java Virtual …

Redis缓存雪崩及解决办法

缓存雪崩 1.缓存雪崩是指在同- -时段大量的缓存key同时失效或者Redis服务宕机&#xff0c;导致大量请求到 达数据库&#xff0c;带来巨大压力。 2.解决方案: ◆给不同的Key的TTL添加随机值 ◆利用Redis集群提高服务的可用性 ◆给缓存业务添加降级限流策略 降级可做为系统的保底…

java程序1补充:从键盘输入圆的半径,求圆的周长和面积(简易与交互两版)

编写一个java程序&#xff0c;从键盘输入圆的半径&#xff0c;求圆的周长和面积&#xff0c;并输出。 要求&#xff1a; &#xff08;1&#xff09;半径仅考虑int型正整数&#xff0c;并综合利用所学较好地处理异常输入&#xff0c;包括非法整数、负整数输入时的处理。输入半…

网络编程套接字基本概念认识

目录 认识端口号 认识TCP协议 认识UDP协议 网络字节序 socket编程接口 socket 常见API sockaddr结构 认识端口号 端口号(port)是传输层协议的内容 端口号是一个2字节16位的整数; 端口号用来标识一个进程, 告诉操作系统, 当前的这个数据要交给哪一个进程来处理; IP地址 …

数字电路仿真编译文件指定方式

目录 1 最基本的方式 2 指定多个文件 3. 使用filelist文件 4 指定整个目录中的所有指定后缀的文件 5 指定include文件的搜索路径 6 追加宏的定义 7 Verdi相关的选项 8 Vivado中的处理方式 1 最基本的方式 最基本的方式就是直接在命令行指定单个源文件&#xff0c;比如说…

VMware安装华为存储模拟器

实验需要的软件&#xff1a; VMware Workstation Pro ST00000000201812000*配套的license文件 Dorado5000 V3存储模拟器磁盘 存储模拟器磁盘和license文件资源&#xff0c;在本人主页发布的资源中去下载 安装步骤&#xff1a; 1. 点击 “文件->新建虚拟机”。 2. 在弹框…

MySQL高级篇(SQL优化、索引优化、锁机制、主从复制)

目录 0 存储引擎介绍1 SQL性能分析2 常见通用的JOIN查询SQL执行加载顺序七种JOIN写法 3 索引介绍3.1 索引是什么3.2 索引优劣势3.3 索引分类和建索引命令语句3.4 索引结构与检索原理3.5 哪些情况适合建索引3.6 哪些情况不适合建索引 4 性能分析4.1 性能分析前提知识4.2 Explain…

SQL Server数据库使用

文章目录 前言一、SQL Server 2008 R2 安装例&#xff1a;安装一台SQL Server 2008 R2服务器 二、SSMS管理工具简介1.SQL Server 2008 R2常用的工具2.连接到服务器 三、SQL Server数据库分类及管理1.SQL Server数据库分类2.SQL Server数据库文件类型3.SQL Server数据库管理例&a…

操作系统第五章——输入输出管理(中)

提示&#xff1a;若我会见到你&#xff0c;事隔经年&#xff0c;我如何向你招呼&#xff0c;以眼泪&#xff0c;以沉默 文章目录 5.2.1 IO核心子系统知识总览功能要在那个层次实现 5.2.2 假脱机技术&#xff08;SPOOLing&#xff09;知识总览什么是脱机技术假脱机技术——输入井…

Kafka锦集(二):三种不同方式,查看kafka是否已启动

前言 Kafka的启动之前&#xff0c;必不可少的三个操作&#xff1a; 1、启动Zookeeper服务&#xff0c;点击进入 bin/zookeeper-server-start.sh -daemon config/zookeeper.properties 2、 Kafka的下载和安装 3、修改Kafka安装目录下./config/server.properties文件里的监听窗…

考研C语言第三章

3.1 运算 #include <stdio.h>int main() {int result45*2-6/310%4;printf("%d\n",result);return 0; }C语言输出上每次都要带着数据类型&#xff0c;想念java 算术运算符与关系运算符 #include <stdio.h>int main() {int a;while(scanf("%d"…

C#,Matlab混合编程(01)——Mat文件格式简介及读写Mat文件的C#源程序

Matlab 软件 20GB&#xff0c;很大&#xff0c;还有卡脖子的问题。 我们可以利用其生成的 Mat 文件做更多的事。 1 Mat 文件 MAT 文件版本概述 MAT 文件是二进制 MATLAB 文件&#xff0c;用于存储工作区变量。从 MAT 文件版本 4 开始&#xff0c;随后的几个 MAT 文件版本都支持…

qtcreator-ros 安装配置

qtcreator-ros 安装配置 计划利用 QT 搭建简易的小车远程控制客户端&#xff0c;QT 系统学习有点耗时&#xff0c;借助 qtcreator-ros 可以缩短开发周期 How to Install (Users) ROS Qt5 librviz人机交互界面开发一&#xff08;配置QT环境&#xff09; 电脑中已经安装 5.10.1 …