实现的功能
注册
登录
查询单词
查询历史记录
大概思路
搭建tcp服务器,通过IO多路复用实现并发(伪并发)。注册:接收到客户端发来的数据,建立一张用户表,将注册信息存储到数据库的用户表中,不过存入之前要判断是否重名 数据可以是一个结构体 可以设置结构中的一个成员为客户端发送过来的指令 客户端根据指令判断是注册 登录 等等。登录同理,不过这时候服务器对数据库表的操作为查询,有注册成功 没有则做其他处理。登录成功后修改登录状态为在线 这个标志位同样存储在结构体中。查询单词 历史记录等同样是对数据库进行查找、插入操作等 这里就不作过多赘述。
下面直接将这个练手的小项目的详细代码分享给大家 希望能帮助到刚入门的你 博客写的不是很规范将就看看吧 内容中若有错误的地方还请指正
定义的结构体:
typedef struct message_user{
char name[20];
char passwd[20];
char wordname[20];
char meaning[128];
int flags;//判断发送的指令
int states;//用户是否在线
int ifuser;//用户名是否存在
int loginflags;// 1成功 2 密码错误 3 用户名不存在
int ifinsearch;//是否查找到对应单词 0没有 1查到
int histroyflags;//1 byuser 2 bywordname
char result[48][128];//历史记录
int num;//查询的记录条数
int column;//字段个数
}info;
注册
int Register(int connfd,sqlite3 *db)
{
char buf[128] = {0};
int ret = sqlite3_open("wmk.db",&db);
if(ret != SQLITE_OK)
{
printf("%s\n",sqlite3_errmsg(db));
return -1;
}
strcpy(buf,"create table if not exists user(name char[10],passwd char[20]);");
char *errmsg = NULL;
ret = sqlite3_exec(db,buf,NULL,NULL,&errmsg);
if(ret != SQLITE_OK)
{
printf("%s\n",errmsg);
return -1;
}
b: bzero(buf,sizeof(buf));
sprintf(buf,"select * from user where name='%s';",message.name);
char **result;
int num = 0;
int column = 0;
if(sqlite3_get_table(db,buf,&result,&num,&column,&errmsg) != SQLITE_OK)
{
printf("%s\n",errmsg);
return -1;
}
if(num > 0)
{
message.ifuser = 1;//用户名已存在
}
else
{
message.ifuser = 0;//用户名不存在
bzero(buf,sizeof(buf));
sprintf(buf,"insert into user values('%s','%s');",message.name,message.passwd);
if(sqlite3_exec(db,buf,NULL,NULL,&errmsg) < 0)
{
printf("%s\n",errmsg);
return -1;
}
}
ret = write(connfd,&message,sizeof(message));
if(ret < 0)
{
perror("write");
return -1;
}
if(message.ifuser == 1)
{
ret = read(connfd,&message,sizeof(message));
goto b;
}
printf("注册\n");
return 0;
}
登录
int Login(int connfd,sqlite3 *db)
{
char buf[128] = {0};
int ret = sqlite3_open("wmk.db",&db);
if(ret != SQLITE_OK)
{
printf("%s\n",sqlite3_errmsg(db));
return -1;
}
a: sprintf(buf,"select * from user where name='%s' and passwd='%s';",message.name,message.passwd);
char *errmsg = NULL;
char **result;
int num = 0;
int column = 0;
ret = sqlite3_get_table(db,buf,&result,&num,&column,&errmsg);
if(ret != SQLITE_OK)
{
printf("%s\n",errmsg);
return -1;
}
if(num)
{
message.loginflags = 1;
message.states = 1;//表示在线
//用户名存在且密码正确
if(write(connfd,&message,sizeof(message)) < 0)
{
perror("write");
return -1;
}
}
else
{
num = 0;
bzero(buf,sizeof(buf));
sprintf(buf,"select *from user where name='%s';",message.name);
ret =sqlite3_get_table(db,buf,&result,&num,&column,&errmsg);
printf("%d\n",ret);
if(ret != SQLITE_OK)
{
printf("%s\n",errmsg);
return -1;
}
//用户名存在密码错误
if(num)
{
message.loginflags = 2;
if(write(connfd,&message,sizeof(message)) < 0)
{
perror("write");
return -1;
}
if(read(connfd,&message,sizeof(message)) < 0)
{
perror("read");
return -1;
}
goto a;
}
else
{
// 用户名不存在
message.loginflags = 3;
if(write(connfd,&message,sizeof(message)) < 0)
{
perror("write");
return -1;
}
if(read(connfd,&message,sizeof(message)) < 0)
{
perror("write");
return -1;
}
goto a;
}
}
printf("登陆\n");
return 0;
}
查询单词
int Insearch(int connfd,sqlite3 *db)
{
if(message.states != 1)
{
if(write(connfd,&message,sizeof(message)) < 0)
{
perror("write");
return -1;
}
return 0;
}
char buf[128] = {0};
char *errmsg = NULL;
char **result;
int num = 0;
int column = 0;
int ret = sqlite3_open("wmk.db",&db);
if(ret != SQLITE_OK)
{
sqlite3_errmsg(db);
return -1;
}
strcpy(buf,"create table if not exists word(word char[128],meaning char[512]);");
ret = sqlite3_exec(db,buf,NULL,NULL,&errmsg);
if(ret != SQLITE_OK)
{
printf("%s\n",errmsg);
return -1;
}
bzero(buf,sizeof(buf));
strcpy(buf,"create table if not exists record(name char[20],time char[128]);");
ret = sqlite3_exec(db,buf,NULL,NULL,&errmsg);
if(ret != SQLITE_OK)
{
printf("%s\n",errmsg);
return -1;
}
bzero(buf,sizeof(buf));
strcpy(buf,"create table if not exists wrecord(wordname char[20],time char[128]);");
ret = sqlite3_exec(db,buf,NULL,NULL,&errmsg);
if(ret != SQLITE_OK)
{
printf("%s\n",errmsg);
return -1;
}
bzero(buf,sizeof(buf));
sprintf(buf,"select * from word where word='%s';",message.wordname);//查找单词
ret = sqlite3_get_table(db,buf,&result,&num,&column,&errmsg);
if(ret != SQLITE_OK)
{
printf("%s\n",errmsg);
return -1;
}
if(num == 0)
{
message.ifinsearch = 0;
if(write(connfd,&message,sizeof(message)) < 0 )
{
perror("write");
return -1;
}
}
else
{
bzero(buf,sizeof(buf));
time_t t;
time(&t);
message.ifinsearch = 1;//查询到单词
strcpy(message.meaning,result[3]);
if(write(connfd,&message,sizeof(message)) < 0)
{
perror("write");
return -1;
}
sprintf(buf,"insert into record values('%s','%s');",message.name,ctime(&t));
ret = sqlite3_exec(db,buf,NULL,NULL,&errmsg);//将查询用户记录到单词用户表中,记录时间
if(ret != SQLITE_OK)
{
printf("%s\n",errmsg);
return -1;
}
bzero(buf,sizeof(buf)) ;
sprintf(buf,"insert into wrecord values('%s','%s');",message.wordname,ctime(&t));
ret = sqlite3_exec(db,buf,NULL,NULL,&errmsg);//将查询记录插入到单词记录表中 记录当前时间
if(ret != SQLITE_OK)
{
printf("%s\n",errmsg);
return -1;
}
}
printf("查询单词\n");
return 0;
}
历史记录(查询的时候插入对应的表中 只需将表中的数据打印出来)
int Histroy_r(int connfd,sqlite3 *db)
{
char **result;
char *errmsg = NULL;
int num = 0;
int column = 0;
char buf[128] = {0};
int ret = 0;
ret = sqlite3_open("wmk.db",&db);
if(ret != SQLITE_OK)
{
sqlite3_errmsg(db);
return -1;
}
if(message.histroyflags == 1)//by user
{
strcpy(buf,"select * from record;");
ret = sqlite3_get_table(db,buf,&result,&num,&column,&errmsg);
if(ret != SQLITE_OK)
{
printf("%s\n",errmsg);
return -1;
}
message.num = num;
message.column = column;
bzero(message.result,sizeof(message.result));
for(int i = 0;i<num * column;i++)
{
strcpy(message.result[i],result[column + i]);
}
if(write(connfd,&message,sizeof(message)) < 0)
{
perror("write");
return -1;
}
/*
for(int i = 0;i < num;i++)
{
for(int j=0;j<column;j++,result++)
{
printf("%s",*(result + 2));
}
//puts("\n");
}
*/
}
else
{
strcpy(buf,"select * from wrecord;");
ret = sqlite3_get_table(db,buf,&result,&num,&column,&errmsg);
if(ret != SQLITE_OK)
{
printf("%s\n",errmsg);
return -1;
}
message.num = num;
message.column = column;
bzero(message.result,sizeof(message.result));
for(int i = 0;i<num * column;i++)
{
strcpy(message.result[i],result[column + i]);
}
if(write(connfd,&message,sizeof(message)) < 0)
{
perror("write");
return -1;
}
}
printf("查找历史记录\n");
return 0;
}
下面是整个客户端的代码
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <unistd.h>
typedef struct message_user{
char name[20];
char passwd[20];
char wordname[20];
char meaning[128];
int flags;//判断发送的指令
int states;//用户是否在线 0 out 1 online
int ifuser;//判断注册是否重名
int loginflags;// 1成功 2 密码错误 3 用户名不存在
int ifinsearch;//是否查找到对应单词 0没有 1查到
int histroyflags;//1 byuser 2 bywordname
char result[48][128];//历史记录
int num;//查询的记录条数
int column;//字段个数
}info;
info message = {0};
int Register(int sockfd)
{
a: printf("请输入用户名:\n");
fgets(message.name,sizeof(message.name),stdin);
message.name[strlen(message.name) - 1] = '\0';
printf("%s\n",message.name);
printf("请输入密码:\n");
fgets(message.passwd,sizeof(message.passwd),stdin);
message.passwd[strlen(message.passwd) - 1] = '\0';
printf("%s\n",message.passwd);
if(write(sockfd,&message,sizeof(message)) < 0)
{
perror("write");
return -1;
}
if(read(sockfd,&message,sizeof(message)) < 0)
{
perror("read");
return -1;
}
if(message.ifuser == 1)
{
printf("用户名已存在请重新输入\n");
goto a;
}
else
{
printf("注册成功\n");
}
sleep(3);
system("clear");
return 0;
}
int Login(int sockfd)
{
b: printf("请输入用户名:\n");
fgets(message.name,sizeof(message.name),stdin);
message.name[strlen(message.name) - 1] = '\0';
c: printf("请输入密码:\n");
fgets(message.passwd,sizeof(message.passwd),stdin);
message.passwd[strlen(message.passwd) - 1] = '\0';
if(write(sockfd,&message,sizeof(message)) < 0)
{
perror("write");
return -1;
}
if(read(sockfd,&message,sizeof(message)) < 0)
{
perror("write");
return -1;
}
switch(message.loginflags)
{
case 1:printf("登陆成功\n");sleep(3);break;
case 2:
{
printf("密码错误,请重新输入\n");
goto c;
break;
}
case 3:
{
printf("用户名不存在,请重新输入\n");
goto b;
break;
}
}
system("clear");
return 0;
}
int Insearch(int sockfd)
{
printf("请输入你要查询的单词:\n");
fgets(message.wordname,sizeof(message),stdin);
message.wordname[strlen(message.wordname) - 1] = '\0';
if(write(sockfd,&message,sizeof(message)) < 0)
{
perror("write");
return -1;
}
if(read(sockfd,&message,sizeof(message)) < 0)
{
perror("write");
return -1;
}
if(message.states != 1)
{
printf("您还未登陆,请先登陆\n");
message.flags = 2;
Login(sockfd);
}
else
{
if(message.ifinsearch == 0)
{
printf("单词库没有此单词\n");
sleep(3);
system("clear");
}
else
{
printf("%s:%s\n",message.wordname,message.meaning);
sleep(3);
system("clear");
}
}
return 0;
}
int Histroy_r(int sockfd)
{
d:
if(message.states != 1)
{
message.flags = 2;
printf("您还未登陆,请登陆\n");
Login(sockfd);
}
else
{
int n = 0;
printf("***1.by user***2.by wordname***\n");
scanf("%d",&n);
getchar();
if(n==1)
{
message.histroyflags = 1;
if(write(sockfd,&message,sizeof(message)) < 0)
{
perror("write");
return -1;
}
if(read(sockfd,&message,sizeof(message)) < 0)
{
perror("write");
return -1;
}
for(int i = 0;i < message.num;i++)
{
printf("%s 在 %s查看了单词\n",*(message.result + 2*i),*(message.result+(2*i + 1)));
}
}
else if(n == 2)
{
message.histroyflags = 2;
if(write(sockfd,&message,sizeof(message)) < 0)
{
perror("write");
return -1;
}
if(read(sockfd,&message,sizeof(message)) < 0)
{
perror("write");
return -1;
}
for(int i = 0;i < message.num;i++)
{
printf("%s 在 %s时被查询了\n",*(message.result + 2*i),*(message.result+(2*i + 1)));
}
}
else
{
printf("输入错误,请重新输入\n");
goto d;
}
}
sleep(3);
system("clear");
return 0;
}
int main(int argc, char *argv[])
{
int sockfd = socket(AF_INET,SOCK_STREAM,0);
if(sockfd < 0)
{
perror("sockfd");
return -1;
}
printf("%d\n",sockfd);
struct sockaddr_in saddr;
bzero(&saddr,sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = inet_addr("192.168.153.128");
saddr.sin_port = htons(8888);
int ret = connect(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
if(ret < 0)
{
perror("connect");
return -1;
}
printf("connect success\n");
while(1)
{
printf("-------欢迎来到英英词典--------\n");
printf("-----1.注册-----2.登陆-----3.查询单词-----4.查看历史记录-----\n");
a: scanf("%d",&message.flags);
getchar();
switch(message.flags)
{
case 1:Register(sockfd);break;
case 2:Login(sockfd);break;
case 3:Insearch(sockfd);break;
case 4:Histroy_r(sockfd);break;
default:printf("输入错误,请重新输入\n");goto a;
}
// printf("++%d\n",message.states);
}
close(sockfd);
return 0;
}
如果都看到这儿了希望不要吝啬您的赞噢 您的阅读点赞是我能够继续坚持的最大动力