接上一小节,本来是计划这一节用来讲数据库的增删改查,但是在实现的过程中,出现了一点小问题,也不是技术的问题,就是在字符界面上比较不好操作。比如要注册一个帐号,就需要弄个字符界面提示,然后输入数字表示选择,在依次输入信息。(这一点,用C写过什么管理系统就知道,很是麻烦。)考虑到本程序讲的是网络编程,就不弄增删改查了,就判断一个用户名密码是否正确就行了。

  首先是安装mysql和创建数据库,所用到的命令如下:

 su root  //使用root用户
yum install mysql-devel*
yum install mysql-server*
service mysqld start

  创建一个users数据库和一个client表

 $mysql -u root
mysql> create database users;
mysql> use users; //切换到users数据库中
mysql> create table clients(id int,username varchar(),password varchar() ); //创建一个叫test的表
mysql> show create table clients; //显示刚才创建的表信息
mysql> select * from clients;   //查询client表中数据
mysql> quit

  1.插入数据

 #include <stdio.h>
#include <mysql.h>
#include <stdlib.h> #define HOST "localhost"
#define USERNAME "root"
#define PASSWORD ""
#define DATABASE "users" int main(int argc,char *argv[])
{
MYSQL conn;
int res;
char *sql="insert into clients values('1','user1','123456');";
mysql_init(&conn); if(mysql_real_connect(&conn,HOST,USERNAME,PASSWORD,DATABASE,,NULL,CLIENT_FOUND_ROWS))
{
printf("Connect Success!\n");
res=mysql_query(&conn,sql);
if(res)
{
printf("Insert Error!\n");
}
else
{
printf("Insert Success!\n");
}
}
else
{
printf("Connect Failed!\n");
exit(-);
}
return ;
}

  2.删除数据

 #include <stdio.h>
#include <mysql.h>
#include <stdlib.h> #define HOST "localhost"
#define USERNAME "root"
#define PASSWORD ""
#define DATABASE "users" int main(int argc,char *argv[])
{
MYSQL conn;
int res;
char *sql="delete from clients where username=\"user1\";"; mysql_init(&conn); if(mysql_real_connect(&conn,HOST,USERNAME,PASSWORD,DATABASE,,NULL,CLIENT_FOUND_ROWS))
{
printf("Connect Success!\n");
res=mysql_query(&conn,sql);
if(res)
{
printf("Delete Error!\n");
}
else
{
printf("Delete Success!\n");
}
}
else
{
printf("Connect Failed!\n");
exit(-);
}
return ;
}

  3.修改数据

 #include <stdio.h>
#include <mysql.h>
#include <stdlib.h> #define HOST "localhost"
#define USERNAME "root"
#define PASSWORD ""
#define DATABASE "users" int main(int argc,char *argv[])
{
MYSQL conn;
int res;
char *sql="update clients set username=\"user2\" where username=\"user1\";";
mysql_init(&conn); if(mysql_real_connect(&conn,HOST,USERNAME,PASSWORD,DATABASE,,NULL,CLIENT_FOUND_ROWS))
{
printf("Connect Success!\n");
res=mysql_query(&conn,sql);
if(res)
{
printf("Update Error!\n");
}
else
{
printf("Update Success!\n");
}
}
else
{
printf("Connect Failed!\n");
exit(-);
}
return ;
}

  4.查询数据

 #include <stdio.h>
#include <mysql.h>
#include <stdlib.h> #define HOST "localhost"
#define USERNAME "root"
#define PASSWORD ""
#define DATABASE "users" int main(int argc,char *argv[])
{
MYSQL conn;
MYSQL_RES *res_ptr;//指向查询结果的指针
MYSQL_FIELD *field;//字段结构体指针
MYSQL_ROW result_row;//按行返回的查询信息 int res;
int i,j;
int row,column;//查询返回的行数和列数
char *sql="select * from clients;";
mysql_init(&conn); if(mysql_real_connect(&conn,HOST,USERNAME,PASSWORD,DATABASE,,NULL,CLIENT_FOUND_ROWS))
{
printf("Connect Success!\n");
res=mysql_query(&conn,sql);
//res=0表示查询成功
if(res)
{
printf("Select Error!\n");
}
else
{
printf("Select Success!\n");
//将查询的结果给res_ptr
res_ptr=mysql_store_result(&conn);
//如果结果不为空,就可以输出了
if(res_ptr)//可以用这个的真假来判断用户名密码是否正确
{
//有结果了
column=mysql_num_fields(res_ptr);//获取列数
row=mysql_num_rows(res_ptr)+;//加1是因为第一行是字段名
printf("查询到的数据有 %d 行\n",row); //输出结果的字段名
for(i=;field=mysql_fetch_field(res_ptr);i++)
{
printf("%s\t",field->name);
}
printf("\n");
//按行输出结果
for(i=;i<row;i++)
{
result_row=mysql_fetch_row(res_ptr);
for(j=;j<column;j++)
{
printf("%s\t",result_row[j]);
}
printf("\n");
}
}
else
{
//没有结果
printf("没有查询到匹配的数据。");
}
}
}
else
{
printf("Connect Failed!\n");
exit(-);
}
mysql_close(&conn);
return ;
}

  对应的makefile

 main:
gcc insert.c `mysql_config --cflags --libs` -o insert
gcc delete.c `mysql_config --cflags --libs` -o delete
gcc update.c `mysql_config --cflags --libs` -o update
gcc select.c `mysql_config --cflags --libs` -o select

  由于本次的重点不是数据库的操作,所以就简单的给出常用的基本方法,在我们的聊天程序中只加入查询用户密码的功能,其他的如注册用户什么的就不写了,应该没有什么难度,就是有点烦。

  加入数据库连接后的聊天程序

  client.c 不变

  server.c 修改如下

  ...
#include <mysql.h>//用于mysql连接   ...
37
void print_time(char * ch,time_t *now)
{
struct tm*stm;
stm=localtime(now);//立即获取当前时间
sprintf(ch,"%02d:%02d:%02d\n",stm->tm_hour,stm->tm_min,stm->tm_sec);
} int mysql_check_login(struct user su)
{
MYSQL conn;
MYSQL_RES *res_ptr;
int res;
int row;
char sql[]={};
strcpy(sql,"select * from clients where username=\"");
strcat(sql,su.name);
strcat(sql,"\" and password=\"");
strcat(sql,su.pwd);
strcat(sql,"\";");
printf("查询的sql:%s\n",sql); mysql_init(&conn);
if(mysql_real_connect(&conn,"localhost","root","","users",,NULL,CLIENT_FOUND_ROWS))
{
res=mysql_query(&conn,sql);
if(res)
{
perror("Select SQL Error!\n");
exit(-);
}
else
{
res_ptr=mysql_store_result(&conn);
if(res_ptr)
{
row=mysql_num_rows(res_ptr);
if(row==)
return ;
return ;//1表示验证成功
}
else
{
return ;//0表示验证失败
}
}
}
else
{
perror("Database Connect Failed!");
exit(-);
}
mysql_close(&conn);
return ;
} int main(int argc,char *argv[])
{
    ...
struct timeval timeout;
struct user use;
time_t now; struct tm *timenow;     ...
while()
{
       ...
switch(select(max_servfd+,&servfd,NULL,NULL,&timeout))
{
case -:
perror("select error");
break;
case :
break;
default:
//printf("has datas to offer accept\n");
if(FD_ISSET(sockfd,&servfd))//sockfd 有数据表示可以进行accept
{
  ...
printf("客户端发来的用户名是:%s,密码:%s\n",use.name,use.pwd);
memset(recvBuf,,sizeof(recvBuf));
if(mysql_check_login(use))
{
printf("验证成功!\n");
strcpy(sendBuf,"yes");
}
else
{
printf("验证失败!\n");
strcpy(sendBuf,"no");
}
if((sendSize=send(clientfd,sendBuf,MAX_DATA_SIZE,))==-)
{
perror("fail to receive datas");
}
              ...
}
break;
}
//FD_COPY(recvfd,servfd);
for(i=;i<MAX_CON_NO;i++)//最大队列进行判断,优化的话,可以使用链表
{
        ...
} switch(select(max_recvfd+,&recvfd,NULL,NULL,&timeout))
{
        ...
}
}
return ;
}

  本次就增加了一个mysql_check_login这个函数用于用户名和密码的判断。也没有加入太多的功能。只要有个大概思路就可以了,剩下的注册和修改基本相似,就不加入到程序中了。

  接下来还是老规矩,上一张运行时的截图

  数据库中的用户名是user1,密码是123456。看,完成了验证了。顿时感觉好极了。

  本文地址: http://www.cnblogs.com/wunaozai/p/3876134.html

Socket网络编程--聊天程序(7)的更多相关文章

  1. Socket网络编程--聊天程序(9)

    这一节应该是聊天程序的最后一节了,现在回顾我们的聊天程序,看起来还有很多功能没有实现,但是不管怎么说,都还是不错的.这一节我们将讲多服务器问题(高大上的说法就是负载问题了.)至于聊天程序的文件发送(也 ...

  2. Socket网络编程--聊天程序(1)

    很早的一段时间,看了APUE和UNPv1了解了网络编程,但是但是只是看而已,没有具体的实践,趁现在没有什么事做,就来实践了解一下网络编程.写博客保存下来,方便以后用到的时候可以查到. 此次的聊天程序是 ...

  3. Socket网络编程--聊天程序(8)

    上一节已经完成了对用户的身份验证了,既然有了验证,那么接下来就能对不同的客户端进行区分了,所以这一节讲实现私聊功能.就是通过服务器对客户端的数据进行转发到特定的用户上, 实现私聊功能的聊天程序 实现的 ...

  4. Socket网络编程--聊天程序(6)

    这一小节将增加一个用户的结构体,用于保存用户的用户名和密码,然后发给服务器,然后在服务器进行判断验证.这里就有一个问题,以前讲的就是发送字符串是使用char类型进行传输,然后在服务器进行用同样是字符串 ...

  5. Socket网络编程--聊天程序(3)

    上一小节,已经讲到可以每个人多说话,而且还没有限制,简单的来说,我们已经完成了聊天的功能了,那么接下来我们要实现什么功能呢?一个聊天程序至少应该支持一对多的通讯吧,接下来就实现多个客户端往服务器发送数 ...

  6. Socket网络编程--聊天程序(4)

    上一小节讲到可以实现多客户端与服务器进行通讯,对于每一个客户端的连接请求,服务器都要分配一个进程进行处理.对于多用户连接时,服务器会受不了的,而且还很消耗资源.据说有个select函数可以用,好像还很 ...

  7. Socket网络编程--聊天程序(5)

    上一小节我们讲了使用select来避免使用多进程的资源浪费问题.上次只是实现了从多个客户端发送数据给服务器端,接下来就要实现从服务器端发送数据给各个客户端. 使用select多路转换处理聊天程序2 c ...

  8. Socket网络编程--聊天程序(2)

    上一节简单如何通过Socket创建一个连接,然后进行通信.只是每个人只能说一句话.而且还是必须说完才会接收到信息,总之是很不方便的事情.所以这一小节我们将对上一次的程序进行修改,修改成每个人可以多说话 ...

  9. Socket网络编程--小小网盘程序(5)

    各位好呀!这一小节应该就是这个小小网盘程序的最后一小节了,这一节将实现最后的三个功能,即列出用户在服务器中的文件列表,还有删除用户在服务器中的文件,最后的可以共享文件给好友. 列出用户在服务器中的文件 ...

随机推荐

  1. Pyinstaller打包附带DLL、图标和压缩EXE方法

    Pyinstaller打包附带DLL.图标和压缩EXE方法     转载: https://blog.csdn.net/xinyingzai/article/details/80282856   目的 ...

  2. hdu 1394 (线段树求逆序数)

    <题目链接> 题意描述: 给你一个有0--n-1数字组成的序列,然后进行这样的操作,每次将最前面一个元素放到最后面去会得到一个序列,那么这样就形成了n个序列,那么每个序列都有一个逆序数,找 ...

  3. js类型判断-丰富加好用

    一, 自己有时候写一些东西,要做类型判断,还有测试的时候,对于原生的和jQuery中的类型判断,实在不敢恭维,所以就写了一个好用的类型判断,一般情况都够用的. function test(type) ...

  4. vuex数据持久化存储

    想想好还是说下vuex数据的持久化存储吧.依稀还记得在做第一个vue项目时,由于刚刚使用vue,对vue的一些基本概念只是有一个简单的了解.当涉及到非父子组件之间通信时,选择了vuex.只是后来竟然发 ...

  5. 获取img的高

    我们可以通过css设置图片的width,然后通过 clientWidth获取图片的宽,但是这个宽似乎是css里面定义的width值,但是对于图片的高,使用 clientHeight 来获取似乎是有些问 ...

  6. HDU.3516.Tree Construction(DP 四边形不等式)

    题目链接 贴个教程: 四边形不等式学习笔记 \(Description\) 给出平面上的\(n\)个点,满足\(X_i\)严格单增,\(Y_i\)严格单减.以\(x\)轴和\(y\)轴正方向作边,使这 ...

  7. og4j日志文件乱码问题的解决方法

    现象:在默认语言非中文(或者说默认语言不支持中文的)的Windows.Linux.Unix上,用log4j打印日志,出现乱码,常见的就是一堆问号. 解决方法: 如果是log4j.properties为 ...

  8. react-native开源组件react-native-wechat学习

    转载链接:http://www.ncloud.hk/%E6%8A%80%E6%9C%AF%E5%88%86%E4%BA%AB/react-native-open-source-components-r ...

  9. 手机号是SIM卡的号呢,还是买手机时就带的

    可以用原来的号码!把原来的卡装在新手机里就可以了,你的号码没有改变! 手机的号是由sim卡来决定的! 但是卡上的号码显示的是卡的一些信息! 你不用去理会它! 全文:http://iask.sina.c ...

  10. C# DES (ECB模式) 加密解密 --单倍长

    加密:  调用时: Encrypt_DES16("2AF349243535BCD3", "1111111111111111"); public static s ...