1.mysql
1).语法问题:
在使用mysql_query这个函数时,一定要注意你执行的命令语句是否正确
例如:
sprintf(sql,"select * from person where passwd = \"%s\";",data->passwd);
mysql_query(&mysql,sql);
如果不确定问题在哪,可执行:
- 可以将sql内的命令打印出来在终端上尝试是否有问题.
- 或者可以将mysql_query返回值打印出来,若是0则成功,若是-1则失败.
2).定义问题:
不知道是为什么在我服务器定义如下会出现段错误内存泄漏问题
MYSQL mysql;
MYSQL_RES *res;
MYSQL_ROW row;
if(NULL == mysql_init(&mysql)){
my_err("mysql_init",__LINE__);
}
if(mysql_library_init(0,NULL,NULL) != 0 ){
my_err("mysql_library_init",__LINE__);
}
if(!mysql_real_connect(&mysql,"127.0.0.1","root","123456","chat",0,NULL,0)){
my_err("mysql_real_connect",__LINE__);
}
if(mysql_set_character_set(&mysql, "utf8") < 0){
my_err("mysql_set_character_set", __LINE__);
}
但是当我重新定义为以下的方式时便成功
MYSQL *myconn;
myconn = mysql_init(NULL);
if(!mysql_real_connect(myconn,"127.0.0.1","root","123456","chat",0,NULL,0)){
fprintf(stderr, "Failed to connect to database: Error: %s\n",
mysql_error(myconn));
}
if(mysql_set_character_set(myconn, "utf8") < 0){
my_err("mysql_set_character_set", __LINE__);
}
我查了资料后得知
MySQL *mysql_init(MYSQL *mysql);
官方文档里说:
Allocates or initializes a MYSQL object suitable formysql_real_connect(). Ifmysql is a NULL pointer, the function allocates, initializes, and returns a new object. Otherwise, the object is initialized and the address of the object is returned. Ifmysql_init() allocates a new object, it is freed whenmysql_close() is called to close the connection
它的意思是,这个函数用来分配或者初始化一个MYSQL对象,用于连接mysql服务端。如果你传入的参数是NULL指针,它将自动为你分配一个MYSQL对象,如果这个MYSQL对象是它自动分配的,那么在调用mysql_close的时候,会释放这个对象。那么,这就有可能出现一个问题,就是,当你主动调用mysql_close之后,可能因为某些原因,又调用一次mysql_close,第二次调用,有可能因为mysql已经是野指针导致程序崩溃。另外,在我的实际运用过程中,有出现一些api调用过程中出错时,自动调用了mysql_close的情况。由于这种自动调用不会被程序感知,因此程序主动close的时候会导致崩溃。为了安全起见,建议不要让mysql_init api自动创建MYSQL对象,而由自己管理这个对象,并且传入地址让它完成初始化,这样,即使你多次调用close函数,也不会出现程序崩溃的现象。
2.事件类型的修改
当在考虑发包问题时,每次服务器端都要向发包的客户端或者向其他客户端进行包的转发,此时在服务器转发过程中总会忘记初始化事件类型,这样收到的包内的事件类型便成为了下一次转发的事件类型,造成程序输出结果混乱,甚至程序阻塞,所以这一问题也是我debug很头疼的一点.
3.包内成员的定义
因为该项目涉及的功能很多,所以一定要在开始定义好包内的成员以及它们的作用都要事先规划好,因为第一次写开始想得比较简单,只定义了收消息和发消息两个字符串数组成员,导致写了一部分后发现包数据不够发的问题,再加上整体结构的问题,导致重构项目,当时直接崩溃,所以一定要事先考虑好.
4.文件的发送
在测试项目时,文件可以传输,但是在服务器和接收的客户端内的文件中会有乱码出现,在将传文件的长度将sizeof(len)
改为strlen(len)
后解决了传输文本文件将包内的多余空间的’\0’传入的问题,但是在测试二进制文件的传输又发现了问题,由于二进制文件中有许多’\0’,导致文件传不完整,所以用strlen
来卡包多余传输的方案也失败了,在查阅了有关文件传输的函数后我想到可以限制发包的大小来发送最后一次read
到的文件个数,最后测试成功.
ssize_t l;
while(1){
if((l = read(fp,send_data->read_buff,sizeof(send_data->read_buff)-1)) < (sizeof(send_data->read_buff)-1)){
//如果读到的字节数小于规定的包的大小,将最后一个包的大小存入l
send_data->flag = 0; //文件最后截止的提示
send_data->mun = l; //文件最后的长度
if(send(connfd,send_data,sizeof(recv_datas),0) < 0){
my_err("send",__LINE__);
}
send_data->cont++;
printf("已发送%d个包\n",send_data->cont);
break;
}