帧同步服务器开发历程

这篇文章将会记录我从0开始学习网络编程后如何实现一个帧同步的游戏服务器
第一版使用了epoll和socket基于protobuf实现了一个简单帧同步服务器1,代码比较多,就没有特地的去加注释,主要的问题简单说一下:
1、用户根据一个.h文件里面写死的账号密码登录,没有实现注册登录功能
2、单线程,在IO的时候会造成cpu的浪费,导致服务器效率变低
3、没有动态的分配内存,虽然会快一点,但是会造成大量的空间被浪费
针对上一版的问题简单的修改了一下新版本服务器2。先说改进的地方
1.实现了用户的注册与登录,并将数据存在MySQL数据库中。
2.加入了Redis,提高效率。
3.实现了多线程,主线程读取完网络消息后塞到消息队列中,交给其他线程处理。
4.除了客户端读取的缓冲区(因为稍微有点麻烦,这个等后面写正式的服务器的时候再改进),其他地方都实现了动态内存分配。
但是这个地方又引出了新的问题,如果仔细看过上面新版本服务器的代码会发现我的SQL和Redis被我封装成了单例,这就导致几个线程调Sql语句的时候会有多线程的问题(其实MySQL是线程安全的),但是因为我的骚操作,导致代码跑起来会出现很多问题。改进方法就是删掉单例代码,在每个线程中都实例化一个SQL对象,分别建立连接,MySQL内部会处理多线程的问题,同时要注意及时的清空结果集

改进后能顺利跑起来的服务器代码,SQLTool.h的代码放到最后。
下方代码虽然能跑起来但依旧存在一个问题:虽然消息是按顺序发来的,多线程也是在队列里面依次去取的,但是多个线程处理完之后放到待发送区却不是依次发过去的,所以还需要保证消息的有序性,解决办法可以在消息结构体最后加上一个序号用来标记,再每帧数据发送前sort一下,然后再依次发送,同时记得去掉最后的序号标记,那玩意客户端用不着,发过去就没必要了。

2022.3.17更新:离大谱,最初的单线程版本处理2500条登录请求算上网络延迟只需要2ms(设置TCP_NODELAY后),多线程的要900毫秒(虽然没设置TCP_NODELA,但这差距也太大了),后来发现可能是我哪辅助线程的原因,最后只开两个线程,主线程收发消息,副线程处理,最终在设置TCP_NODELAY的情况下,算上网络延迟总算是提高到了20ms,这里得出结论:消息处理很简单的话没必要开多线程

mark一下,怕忘记Linux下编译的指令,要加上protobuf还有sql还有多线程的模块所以编译指令很长: g++ FileName.cpp GameMessage.pb.cc -o FileName -std=c++11 -lprotobuf -I/usr/include/mysql/ -L/usr/lib64/mysql -L/usr/local/lib/ -lmysqlclient_r -lhiredis -lpthread

SQLTool.h的代码如下

#pragma once
#include <hiredis/hiredis.h>
#include <mysql.h>
#include <unistd.h>
#include <iostream>
#include <vector>
#include <string>
#include <cstring>
#include <cstdio>
#include <cstdint>
#include <cstdlib>

#include <pthread.h>
using namespace std;
class SQLTool
{
   
public:
    SQLTool();

    bool init();

    //暂时不提供修改地址、数据库账户密码的接口
    void setPort(int32_t iPort) {
    m_iPort = iPort; }
    int32_t getPort() {
    return m_iPort; }

    void setHost(string strHost) {
    m_strHost = strHost; }
    string getHost() {
    return m_strHost; }

    void setTable(string strTableName) {
    m_strTableName = strTableName; }
    string getTable() {
    return m_strTableName; }
    //数据库操作接口(根据表的类型来增加接口)
    bool getPassWord(string strUsername,string &strPassWord);
    bool setPassWord(string strUsername, string strNewPassWord);
    bool addUser(string strUserName, string strPassWord);
    bool deleteUser(string strUserName);
    
    //关闭数据库连接
    void closeSql(){
   
        mysql_close(&m_sqlHandler);
    }
private:

    pthread_mutex_t mute
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值