Raknet和新版本MySQL兼容性问题

        先说结论,细节待补充。

        目前发现两处问题:

1、Raknet自带的AutoPatcher服务器,初始化DB时有一句:

"modificationDate double precision DEFAULT EXTRACT(EPOCH ......),"

(AutopatcherMySQLRepository.cpp  Line 83)

根据百度来的说法,MySQL不支持以函数作为默认值。所以这个地方运行时会报错,我将其改为DEFAULT 0.0,然后修改代码。

具体是在同一个文件两处调用“INSERT INTO FileVersionHistory”的时候,显式的给modificationDate赋值,利用C语言标准库的time.h获得当前时间放进去就可以了。

这么以来,数据库表创建似乎是ok了,但发现下载不了。


2、客户端下载patcher时,每次服务器传来的都是0字节数据,根本不能下载。

Raknet代码还是挺复杂的,连续调试了两三天代码,发现问题还是出在 AutopatcherMySQLRepository.cpp 这个文件,下面这句:

sprintf(query, "SELECT substring(content from %i for %i) FROM FileVersionHistory WHERE fileId=%i;", startReadBytes+1,numBytesToRead,context.fileId);

这句查询会失败,原因还不清楚。晚上或者明天补充一下。


———————————咚咚咚,次日—————————————————————————————————————————————————————————

        AutoPatcher不能用的问题基本搞定了,先说结论:Raknet底层操作MySQL数据库时,连接用的参数处理不当,导致在Linux下二次连接数据库会失败。

        遇到复杂问题都得先从基本程序开始做做试验:

//我自己写的测试代码:

#include "MySQLInterface.h"
#include <stdio.h>
#include "mysql/mysql.h"  // MYSQL_RES

int main()
{
    MySQLInterface sql;
    bool success = sql.Connect("localhost", "root", "1", "swift", 0, NULL, 0);
    if (!success)
    {
        printf("failed connect: %s\n", sql.GetLastError());
        return -1;
    }
    else
    {
        printf("connected: %d\n", sql.IsConnected());
    }
}
        如上,利用Raknet对MySQL的简单封装,写出来的连接操作就是上面黑体字那样的。注意倒数第二个参数:unix_socket,这个参数如果不需要,必须为NULL而不能是空字串"",空字串会导致连接失败。您先别急试,传NULL会导致MySQLInterface的底层崩溃,是这么崩的:

// DependentExtensions/MySQLInterface/MySQLInterface.cpp

bool MySQLInterface::Connect(const char *host,
							 const char *user,
							 const char *passwd,
							 const char *db,
							 unsigned int port,
							 const char *unix_socket,
							 unsigned long clientflag)
{
	if (IsConnected())
		return false;

	_host=host;
	_user=user;
	_passwd=passwd;
	_db=db;
	_port=port;
	_unix_socket=unix_socket;
	_clientflag=clientflag;

	mySqlConnection = mysql_init(0);
	return mysql_real_connect (mySqlConnection, host, user, passwd, db, port, unix_socket, clientflag) != 0;
}
//其中,这些下划线开头的成员的类型为:
	// Copy of connection parameters
	RakNet::RakString _host;
	RakNet::RakString _user;
	RakNet::RakString _passwd;
	RakNet::RakString _db;
	unsigned int _port;
	RakNet::RakString _unix_socket;
	unsigned long _clientflag;


         也就是说,它们是RakString类型,无法表示NULL,而且赋值为NULL会导致Segmentation fault。

        另外,在下载Patcher的时候,调用的是:

//AutopatcherMySQLRpository.cpp 函数AutopatcherMySQLRepository::GetFilePart的片段:
	if (filePartConnection==0)
	{
		filePartConnection = mysql_init(0);
		mysql_real_connect(filePartConnection, _host, _user, _passwd, _db, _port, _unix_socket, _clientflag);
        一来,上面说了这个_unix_socket不是NULL,会导致连不上,而且没有判断是否成功。非常难查。

        二来,发现了吗,RakString传参时可以直接当作C字符串来用,这个设计值得学习。如果像我一样觉得不爽,就用RakString的C_String()方法转换成正确的类型。


        总之是个很讨厌的问题。而且还不是很好改。我最大的收获是通过这个BUG把Raknet源码好好跟了下 :)





你可能感兴趣的:(mysql,数据库,socket,unix,user,null)