程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> MySQL綜合教程 >> 分享封裝好的異步Mysql動態的庫(DyNetMysql.dll) + 項目源碼,mysql異步

分享封裝好的異步Mysql動態的庫(DyNetMysql.dll) + 項目源碼,mysql異步

編輯:MySQL綜合教程

分享封裝好的異步Mysql動態的庫(DyNetMysql.dll) + 項目源碼,mysql異步


在做C++項目時,經常會用到Mysql數據庫,Mysql接口提供給我們的數據是相當原始的,如:字段名、字段類型,字段長度等等,一般情況我們都想一種更方便獲得數據

如:

XXXStruct* pRecourdInfo = (const XXXStruct*)(mysql獲得的數據指針);

直接轉換字段對應的結構來,這樣能大大方便我們使用

這個功能已經在我之前發表上一篇文章<<分享一直在維護簡單實用高效的C++Socket框架Swa-server(開源+源碼)>>中實現,現在是將它封裝成為一個dll

最近有點時間,就學習了dll相關知識,然後將封裝成一個dll,這樣方便使用及移植到其他項目。於是將swa-server中的mysql異步處理功能代碼分離出來,創建一個DyNetMysql項目,設置為dll項目

關於dll項目及導出不要這裡講述,園友自己百度查詢(zf把谷歌封了真是服了)

根據園友性格就先上代碼(*_*)

// TestDll.cpp : 定義控制台應用程序的入口點。
//

#include "stdafx.h"
#include "../../DyNetServer/NetServer.h"
#include "../../DyNetMysql/DbSession.h"
#include "../../DyNetMysql/DbRecordSet.h"

#include <iostream>
using namespace std;

NetServer*	gNetServer;
IDbSession*	gDataBase;

void OnNetMsgEnter( NetSocket& rSocket );
void OnNetMsgExit( NetSocket& rSocket );
void OnNetMsg( NetSocket& rSocket , NetMsgHead* pHead );

#pragma pack(push,1)
struct CharacterInfo
{
	int64 type_idx;
	char nick[32];
	int32 level;
};
#pragma pack(pop)

void DBCallbase(void* pUser, const void* pMsg)
{
	const DbRecordSet* pRecordSet = static_cast<const DbRecordSet*>(pMsg);
	for (int32 i = 0 ; i < pRecordSet->CountRecord();++i )
	{
		const CharacterInfo* pInfo = static_cast<const CharacterInfo*>(pRecordSet->GetRecordBuff(i));
		printf("id:%ld nick:%s level:%d \n",pInfo->type_idx,pInfo->nick,pInfo->level);
	}
}

int _tmain(int argc, _TCHAR* argv[])
{

	// 啟動msyql
	gDataBase = DbSessionMgr::Instance()->AddDatabase("127.0.0.1", "root", "root", "swa_data", false);
	ASSERT(gDataBase);

	// 初始化Scoket服務
	gNetServer = NetServerMgr::Instance()->AddNetServer();
	gNetServer->SetAddress("127.0.0.1", 4321);
	gNetServer->SetHandler(OnNetMsgEnter, OnNetMsg, OnNetMsgExit);

	// 啟動Socket服務
	gNetServer->Start();

	gDataBase->ExecuteAsyncSQL("SELECT `type_idx`,`nick`,`level` FROM `character`",NULL,DBCallbase);
	while (true)
	{
		Sleep(1);
		NetServerMgr::Instance()->Update(0); //邏輯處理
		DbSessionMgr::Instance()->Update(0); //SQL處理及回調
	}
	return 0;
}

void OnNetMsgEnter(NetSocket& rSocket)
{
	int a = 1;
}

void OnNetMsg(NetSocket& rSocket, NetMsgHead* pHead)
{
	int a = 1;
}

void OnNetMsgExit(NetSocket& rSocket)
{
	int a = 1;
}

這裡啟動創建一個Mysql連接對象,如果成功返回!null,然後可以異步執行sql及設置回調(可以不設置回調)

上述代碼運行效果圖如下(為什麼用printf,如果是字符放在第二以上顯示為<null>,園友如果知道是什麼原因,LZ感激不盡):

其實實現將數據直接轉結構體也不是很難,即每行給一個char buffer[65536],然後將mysql的字段內存拷貝進去,之後再轉為結構體即可

這裡需要注意的,如果是char或varchar字段的,轉出來要知道mysql是用什麼字符編碼,如果是utf-8則它byte最大長度為定義長度*3,本dynetmysql是按utf-8,且長度默認為字節長度,所以存儲是中文時要注意,一個中文是用3個長度。

相關類部分代碼1:

    DbRecordSet&    m_rRecordSet;
    vector<DbField>    m_vecFields;
    char            m_arrRowBuff[65536]; // 每一行內容記錄,每個字段記錄它的開始位置即可,則一行記錄最大為64k 
    uint32            m_nBuffBegin; // 已經使用的位置

相關類部分代碼2:

    switch (nType)
    {
    case FIELD_TYPE_TINY:
    {
        mI64Val = pszValue ? atol(pszValue) : 0;
        memcpy(&m_arrRowBuff[m_nBuffBegin], &mI64Val, 1);
        m_nBuffBegin += 1;
    }
        break;
    case FIELD_TYPE_SHORT:
    {
        mI64Val = pszValue ? atol(pszValue) : 0;
        memcpy(&m_arrRowBuff[m_nBuffBegin], &mI64Val, 2);
        m_nBuffBegin += 2;
    }
        break;
    case FIELD_TYPE_LONG:
    {
        mI64Val = pszValue ? atol(pszValue) : 0;
        memcpy(&m_arrRowBuff[m_nBuffBegin], &mI64Val, 4);
        m_nBuffBegin += 4;
    }
        break;
    case FIELD_TYPE_FLOAT:
    {
        mF64Val = pszValue ? atof(pszValue) : 0;
        memcpy(&m_arrRowBuff[m_nBuffBegin], &mF64Val, 4);
        m_nBuffBegin += 4;
    }
        break;
    case FIELD_TYPE_LONGLONG:
    {
        mI64Val = pszValue ? atol(pszValue) : 0;
        memcpy(&m_arrRowBuff[m_nBuffBegin], &mI64Val, 8);
        m_nBuffBegin += 8;
    }
        break;
    case FIELD_TYPE_DOUBLE:
    {
        mF64Val = pszValue ? atof(pszValue) : 0;
        memcpy(&m_arrRowBuff[m_nBuffBegin], &mF64Val, 8);
        m_nBuffBegin += 8;
    }
        break;
    case FIELD_TYPE_STRING:// char
    case FIELD_TYPE_VAR_STRING:// var_char
    {
        memcpy(&m_arrRowBuff[m_nBuffBegin], pszValue, nLen / 3); // mysql char 定義大小會按最大長底去計算長度,這裡限制按字節大小去截斷
        m_nBuffBegin += nLen / 3;
    }
        break;
    case MYSQL_TYPE_TINY_BLOB:
    case MYSQL_TYPE_MEDIUM_BLOB:
    case MYSQL_TYPE_LONG_BLOB:
    case MYSQL_TYPE_BLOB:
    {
        memcpy(&m_arrRowBuff[m_nBuffBegin], pszValue, nLen);
        m_nBuffBegin += nLen;
    }
        break;

目前這個DyNetMysql.dll還不完善,如果是直接select 則可以創建結構體與它對應則可直接轉結構體,如果是其它如update,delete乖等,則建議設置不使用回調或使用存儲過程。

測試代碼中也用到了最近封裝一個異步Socket的dll,如果大家感興趣,請留言和推薦吧,我才會有動力跟園友一起分享!如果有問題,可以留言或qq296464231問我

項目源碼下載

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved