简易聊天室四 注册用户
来源:互联网 发布:ubuntu连接wifi命令 编辑:程序博客网 时间:2024/05/11 16:37
简易聊天室四 注册用户
断断续续几天的功夫,终于把注册用户的功能加好了,真的是好就没有写程序了,这几天把数据库的知识又好好的复习了一下,想着是赶紧给大家带来这篇博客,自己在学习过程中遇到的东西,也希望和大家分享一下。
在前几章的博客中,我们搭建好了TCP/IP框架,分析了线程和界面,今天开始,我们就要开始往程序中写功能了。就像QQ一样,一切的功能伊始,首先得注册一个用户,对于用户注册信息的存储和维护,对后面的其他功能,都起到了至关重要的作用。
一.sqlite3数据库
SQLite,是一款轻型的数据库,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。它能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如 Tcl、C#、PHP、Java等,还有ODBC接口,同样比起Mysql、PostgreSQL这两款开源的世界著名数据库管理系统来讲,它的处理速度比他们都快。我们使用它的最新版——sqlite3。
在使用sqlite3之前,先让我们看看应该如何安装:
数据库其他的东西,就是通过sqlite语句调用sqlite3_exec函数执行函数的传入数(据库指针,sqlite语句,回调函数(也可以null),回调函数实参,错误信息输出)。大家可以通过程序,多加训练。
main.c
main.c
在前几章的博客中,我们搭建好了TCP/IP框架,分析了线程和界面,今天开始,我们就要开始往程序中写功能了。就像QQ一样,一切的功能伊始,首先得注册一个用户,对于用户注册信息的存储和维护,对后面的其他功能,都起到了至关重要的作用。
一.sqlite3数据库
SQLite,是一款轻型的数据库,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。它能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如 Tcl、C#、PHP、Java等,还有ODBC接口,同样比起Mysql、PostgreSQL这两款开源的世界著名数据库管理系统来讲,它的处理速度比他们都快。我们使用它的最新版——sqlite3。
在使用sqlite3之前,先让我们看看应该如何安装:
1.去sqlite主页http://www.sqlite.org/.跳转到下载也http://www.sqlite.org/download.html。源码下载sqlite-amalgamation-3.7.3.tar.gz
2.进入下载目录,解压文件tar -zxvf sqlite-amalgamation-3.7.3.tar.gz. 解压后生成sqlite-3.7.3目录. cd 进入sqlite-3.7.3。
3./configure
make
sudo make install
安装完成。
sqlite3给我提供了很多的接口函数供我们使用,使我们在程序中可以很方便的创建,插入,查询,删除数据库,下面是几个常见的功能,我把代码贴出来:
#include <stdio.h>#include <sqlite3.h>#include <unistd.h>#include <stdlib.h>#include <string.h>int callback(void *arg,int n,char**result,char**name){int i = 0;for(i = 0 ; i < n ; i++){if(strcmp(name[i],"id") == 0 ){printf("%s\n",result[i]);}}return 0;}int main(){sqlite3 *db;char *errmsg;sqlite3_open("newdb.db",&db);//创建/打开数据库/**/char sql[128];char name[10] = {0};memset(sql, '\0', 128); sprintf(sql, "%s%s%s", "create table ", "test_tb","(id INTEGER PRIMARY KEY, data TEXT);"); //创建表格sqlite3_exec(db, sql, NULL, NULL, &errmsg);printf("%s\n",errmsg);/**/memset(sql, '\0', 128); sprintf(sql,"%s%s%s","insert into ","test_tb(id,data)","values(19,'shijie')"); //插入一组数据sqlite3_exec(db, sql, NULL, NULL, NULL); sprintf(sql,"%s%s%s","insert into ","test_tb(id,data)","values(22,'shichengcheng')"); //插入一组数据sqlite3_exec(db, sql, NULL, NULL, NULL);sprintf(sql,"%s%s%s","insert into ","test_tb(id,data)","values(24,'songtao')"); //插入一组数据sqlite3_exec(db, sql, NULL, NULL, NULL);/**/memset(sql, '\0', 128); sprintf(sql,"update test_tb set id=22,data='fyb'where id=21"); //索引修改一组数据sqlite3_exec(db, sql, NULL, NULL, NULL);/**/memset(sql, '\0', 128); sprintf(sql,"delete from test_tb where id=19"); //索引删除一组数据sqlite3_exec(db, sql, NULL, NULL, NULL);/**/ //sqlite3_exec(db, "drop table test_tb", NULL, NULL, NULL); //删除数据表 /**/char ** azResult; //sqlite3_get_table()解析数据库int nrow = 0;int ncolumn = 0;sqlite3_get_table(db ,"select * from test_tb" , &azResult , &nrow , &ncolumn , &errmsg);printf("nrow = %d, ncolumn = %d\n",nrow,ncolumn);printf("msg = %s\n",errmsg);printf("%s|%s\n",*(azResult+0),*(azResult+1));printf("%s|%s\n",*(azResult+2),*(azResult+3));printf("%s|%s\n",*(azResult+4),*(azResult+5));printf("%s|%s\n",*(azResult+6),*(azResult+7));sqlite3_free_table( azResult );printf("\n\n\n");/**/sqlite3_exec(db, "select * from test_tb",callback, NULL, NULL);sqlite3_close(db);return 0;}对于最后一个遍历数据库
sqlite3_exec(db, "select * from test_tb",callback, NULL, NULL);等于就是我们下达“select * from test_tb”命令,使之遍历数据库,然后我们传入一个回调函数,在它遍历数据库的过程,我们乘机寻找我们需要找的东西,在这里面,有一点一定要牢记,callback函数一定要加return 0;否则,遍历不会成功,读者可以复制程序后删除语句后试试。
数据库其他的东西,就是通过sqlite语句调用sqlite3_exec函数执行函数的传入数(据库指针,sqlite语句,回调函数(也可以null),回调函数实参,错误信息输出)。大家可以通过程序,多加训练。
二.枚举enum{};
枚举enum介绍
在这里,博主主要想给大家传达一个思想,对于一个大型程序,难免会有很多的分支选择程序,判断执行。最典型的就是switch case;很多童鞋一开始写程序,满篇程序都是幻数,如果-1,执行什么,如果是3,执行什么,这样子写程序,不仅调理不清,而且给其他人甚至自己日后读取程序都加大难度。
enum {LOG,REG}; //登录 注册 enum {OK,NO};三.信息包用同一个结构体
这个是方便我们开发程序,我们在进行通讯的时候,会发送不同类型的数据,发送id,发送name,发送聊天内容,有的时候发送数据还不止一种,所以,使用一个统一的数据库,很大程度上可以使我们少去烦恼我们怎么打包发送。
myhead.h
#include <sys/types.h> /* See NOTES */#include <sys/socket.h>#include <arpa/inet.h>#include <netinet/in.h>#include <string.h>#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <unistd.h>#include <pthread.h>#include <sqlite3.h>#include <time.h> enum {LOG,REG};enum {OK,NO};typedef struct chat_b //目前只需要这些,以后会逐一增加{int action;char regName[10];char regPassword[30];long logId;char logPassword[30];int ack;}chat_t;
下面是各主程序
客户端:
welcome.c
#include "myhead.h"void welcome(void){system("clear");printf("\n\n\n\n\n\n");printf("\t\t\t\t\t\033[47;34m\t\t\t\t\t\t\t\t\033[0m\n");printf("\t\t\t\t\t\033[47;34m\t\t\t 简易聊天室 \t\t\t\033[0m\n");printf("\t\t\t\t\t\033[47;34m\t\t\t\t\t\t\t\t\033[0m\n");printf("\n\n");printf("\t\t\t\t\t\033[47;34m\t\t\t\t\t\t\t\t\033[0m\n");printf("\t\t\t\t\t\033[47;34m\t\t\t A: Log \t\t\t\t\033[0m\n");printf("\t\t\t\t\t\033[47;34m\t\t\t\t\t\t\t\t\033[0m\n");printf("\t\t\t\t\t\033[47;34m\t\t\t\t\t\t\t\t\033[0m\n");printf("\t\t\t\t\t\033[47;34m\t\t\t\t\t\t\t\t\033[0m\n");printf("\t\t\t\t\t\033[47;34m\t\t\t\t\t\t\t\t\033[0m\n");printf("\t\t\t\t\t\033[47;34m\t\t\t B: Reg \t\t\t\t\033[0m\n");printf("\t\t\t\t\t\033[47;34m\t\t\t\t\t\t\t\t\033[0m\n");printf("\t\t\t\t\t\033[47;34m\t\t\t\t\t\t\t\t\033[0m\n");printf("\t\t\t\t\t\033[47;34m\t\t\t\t\t\t\t\t\033[0m\n");printf("\t\t\t\t\t\033[47;34m\t\t\t\t\t\t\t\t\033[0m\n");printf("\t\t\t\t\t\033[47;34m\t\t\t C: Exi \t\t\t\t\033[0m\n");printf("\t\t\t\t\t\033[47;34m\t\t\t \t\t\t\t\t\033[0m\n");}int Log(int clientfd,chat_t *client_struct);int reg(int clientfd,chat_t *client_struct);void welcome_menu(int clientfd,chat_t *client_struct){char welc_choice[10];wel:memset(welc_choice,0,sizeof(welc_choice));welcome();printf("请输入您的选择:");scanf("%s",welc_choice);if(strcmp("Log",welc_choice) == 0){//printf("in Log\n");Log(clientfd,client_struct);}else if(strcmp("Reg",welc_choice) == 0){//printf("in Reg\n");reg(clientfd,client_struct);}else if(strcmp("Exi",welc_choice) == 0){//printf("in Exi\n");exit(0);}else{//printf("error\n");printf("输入无效指令(Log,Reg,Exi)\n");goto wel;sleep(2);}sleep(2);goto wel;}int Log(int clientfd,chat_t *client_struct){//write(clientfd,"Log",3);client_struct->action = LOG;write(clientfd,client_struct,sizeof(chat_t));}int reg(int clientfd,chat_t *client_struct){//write(clientfd,"reg",3);char stmPassword[30];srand((unsigned) time(NULL));reg:client_struct->action = REG;printf("请输入您的昵称:\n");scanf("%s",client_struct->regName);if(strcmp("admin",client_struct->regName) == 0){printf("管理员无法被注册\n");memset(client_struct,0,sizeof(chat_t));goto reg;}printf("请输入您的密码:\n");scanf("%s",client_struct->regPassword);printf("请确认您的密码:\n");scanf("%s",stmPassword);if(strcmp(stmPassword,client_struct->regPassword) == 0){client_struct->logId = rand() % 100000;write(clientfd,client_struct,sizeof(chat_t));read(clientfd,client_struct,sizeof(chat_t));if(client_struct->ack == OK){}else{printf("昵称已存在!\n");memset(client_struct,0,sizeof(chat_t));goto reg;}printf("请记住您的ID:%d\n",client_struct->logId);sleep(4);}else{memset(client_struct,0,sizeof(chat_t));memset(stmPassword,0,sizeof(stmPassword));goto reg;}}
main.c
#include "./myhead.h"#define PORT 8900extern void welcome(void);extern void welcome_menu(int client_fd,chat_t *client_struct);int main(char argc, char **argv){int clientfd = socket(AF_INET,SOCK_STREAM,0);chat_t client_struct = {0};if(clientfd < 0){fprintf(stderr,"socketfd failed");}struct sockaddr_in server_addr;memset(&server_addr,0,sizeof(struct sockaddr_in));server_addr.sin_family = AF_INET; server_addr.sin_port = htons(8900); server_addr.sin_addr.s_addr = htons(INADDR_ANY);if(-1 ==connect(clientfd,(struct sockaddr*)&server_addr,sizeof(struct sockaddr))){printf("connect failed!\n");close(clientfd);return -1;}welcome_menu(clientfd,&client_struct);//while(1);close(clientfd);return 0;}
服务器
client_thread.c
#include "../client/myhead.h"int Log(int client_fd,chat_t *chat_struct);int reg(int client_fd,chat_t *chat_struct);sqlite3 *db;chat_t *client_struct;int callback_reg(void *arg,int n,char**result,char**name); void *client_thread(void *arg){int client_fd = *(int *)arg;//取出accept_fd,用于信息的传输chat_t chat;client_struct = &chat; // 如果没有这句,client_struct 是野指针//char rev_buf[20] = {0};int i = 0;//printf("%d\n",client_fd);//while(i--)//{//read(client_fd,rev_buf,20);//printf("%s\n",rev_buf);//memset(rev_buf,0,20);//}sqlite3_open("client_db",&db);sqlite3_exec(db, "create table client_tb (id INTEGER PRIMARY KEY, name TEXT,passward TEXT,online INTEGER);", NULL, NULL, NULL);while(1){memset(client_struct,0,sizeof(chat_t));read(client_fd,client_struct,sizeof(chat_t)); // read(client_fd,client_struct,sizeof(client_struct)); 指针和指针内容printf("%s\n%s\n",client_struct->regName,client_struct->regPassword);printf("%d,i=%d,fd=%d\n",client_struct->action,i++,client_fd);switch(client_struct->action){case LOG:Log(client_fd,client_struct);break;case REG:reg(client_fd,client_struct);break;default:break;}}}int Log(int client_fd,chat_t *chat_struct){//printf("Log\n");}int reg(int client_fd,chat_t *chat_struct){//printf("Reg\n");char sql[100] = {0};chat_struct->ack = OK;sqlite3_exec(db,"select * from client_tb",callback_reg,chat_struct,NULL);write(client_fd,chat_struct,sizeof(chat_t));if(chat_struct->ack == NO){return 0;}sprintf(sql,"insert into client_tb(id, name,passward,online)values(%d,'%s','%s',0)",chat_struct->logId,chat_struct->regName,chat_struct->regPassword);sqlite3_exec(db,sql,NULL,NULL,NULL);}int callback_reg(void *arg,int n,char**result,char**name){chat_t *p = (chat_t*)arg;int i = 0;for(i = 0 ; i < n ; i++){if(strcmp(name[i],"name") == 0 ){if(strcmp(p->regName,result[i]) == 0){p->ack = NO;}}}return 0;}
main.c
#include "../client/myhead.h"extern void*client_thread(void*arg);int main(char argc,char **argv){int sockfd = socket(AF_INET,SOCK_STREAM,0); //AF_INET=IPV4; SOCK_STREAM 流传输if(sockfd < 0){fprintf(stderr,"server socket failed!\n"); //stderr 标准错误输出return -1;}struct sockaddr_in server_addr;memset(&server_addr,0,sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_port = htons(8900);server_addr.sin_addr.s_addr = htons(INADDR_ANY);bzero(&(server_addr.sin_zero),0);if(bind(sockfd,(struct sockaddr*)&server_addr,sizeof(struct sockaddr)) < 0){fprintf(stderr,"bind failed!\n");return -1;}if(listen(sockfd,7) < 0){perror("listen failed!");return -1;}struct sockaddr_in client_addr;int accept_fd;char buff[5] = {0};pthread_t client_fd;socklen_t client_len = sizeof(struct sockaddr);while(1){accept_fd = accept(sockfd,(struct sockaddr *)&client_addr,&client_len);int *p;*p = accept_fd;pthread_create(&client_fd,NULL,client_thread,(void *)p);pthread_detach(client_fd);}close(sockfd);return 0;}
在写程序的时候,我遇到了两个问题,卡了我一些时间一个是野指针,一个是指针和指针内容
0 0
- 简易聊天室四 注册用户
- 简易聊天室五 用户登录
- 简易聊天室
- 简易的用户注册和登录系统.
- 简易版 用户注册(Struts2)
- 简易聊天室的制作
- 简易局域网聊天室程序
- Java简易聊天室
- 简易多人聊天室
- socket简易聊天室
- ASP.net--简易聊天室
- Websocket学习--简易聊天室
- 简易网页聊天室DEMO
- 搭建简易在线聊天室
- 网络编程 简易聊天室
- JAVA--简易聊天室程序
- JSP简易聊天室
- java简易多用户聊天室
- Sql常见面试题 受用了
- Android电池驱动(三)(自用)
- [置顶]iOS开发-多线程编程技术(Thread、Cocoa operations、GCD)
- [置顶]Git-学习笔记(常用命令集合)
- [置顶]iOS开发-多线程开发之线程安全篇
- 简易聊天室四 注册用户
- [置顶]MySQL之终端(Terminal)管理MySQL
- [置顶]MySQL之终端(Terminal)管理数据库、数据表、数据的基本操作
- [置顶]Swift 与 Object-C 交互 (Swift版本为:1.2)
- [置顶]将博客搬至CSDN
- 分享:关于如何使用反编译器,获取源码清单方法
- Java执行shell脚本关闭远程数据库
- 科学阅读的基本原则是什么
- Android中管理多个Fragment的最佳实践,完美解决保存状态与重影问题