流程图
1.注册
2.登录
3.查询单词
4.查询历史记录
5.退出登录
服务器代码
main.c
#include "ser.h"
struct sockaddr_in clis[1024];//存放地址信息
sqlite3 *db;
int main(int argc,const char *argv[])
{
//创建数据库,导入辞典
//sqlite3 *db;
if(sqlite3_open("dict.db",&db) != SQLITE_OK)
{
fprintf(stderr,"sqlopen:%s line:%d",sqlite3_errmsg(db),__LINE__);
return -1;
}
//创建辞典表,用户表,历史记录表
char *errmsg;
if(sqlite3_exec(db,"create table if not exists dict(word char parmary key,mean char);"
"create table if not exists users(user char parmary key,pwd char);"
"create table if not exists history(user char,word char,time char);"
,NULL,NULL,&errmsg) != SQLITE_OK)
{
fprintf(stderr,"sqlcreate:%s line:%d",errmsg,__LINE__);
return -1;
}
//判断辞典是否有值
int row = 0,col = 0;
char **result = NULL;
if(sqlite3_get_table(db,"select * from dict",&result,&row,&col,&errmsg) != SQLITE_OK)
{
fprintf(stderr,"sqlgettable:%s line:%d",errmsg,__LINE__);
return -1;
}
//printf("%d %d %s\n",row,col,result[0]);
sqlite3_free_table(result);
//导入辞典
if(row == 0) if(importDict(db)) return -1;
puts("辞典导入完成");
//创建tcp服务器
int sfd = socket(AF_INET, SOCK_STREAM, 0);
if(sfd < 0)
{
ERR_MSG("socket");
return -1;
}
//允许端口快速被重用
int reuse = 1;
if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
{
ERR_MSG("setsockopt");
return -1;
}
struct sockaddr_in addr={AF_INET,htons(PORT),inet_addr(IP)};
if(bind(sfd,(struct sockaddr*)&addr,sizeof(addr)) < 0)
{
ERR_MSG("bind");
return -1;
}
if(listen(sfd, 128) < 0)
{
ERR_MSG("listen");
return -1;
}
printf("服务器启动成功\n");
socklen_t cinlen = sizeof(struct sockaddr_in);
while(1)
{
struct sockaddr_in clitemp;
int fd = accept(sfd,(struct sockaddr*)&clitemp,&cinlen);
if(fd < 0)
{
ERR_MSG("socket");
return -1;
}
printf("[%s:%d] %d 客户端已连接\n",inet_ntoa(clitemp.sin_addr),ntohs(clitemp.sin_port),fd);
clis[fd] = clitemp;
pthread_t tid;
if(pthread_create(&tid,NULL,dictSystem,&fd) < 0)
{
ERR_MSG("pthread_create");
return -1;
}
pthread_detach(tid);
}
sqlite3_close(db);
close(sfd);
return 0;
}
ser.h
#ifndef __SER_H__
#define __SER_H__
#include <myhead.h>
#define IP "192.168.125.106"
#define PORT 8888
#define REGISTER 1
#define LOGON 2
#define WORDQUERY 3
#define HISTORY 4
#define QUIT 5
int importDict();//导入辞典
void *dictSystem(void *arg);//线程体
int dictRegister(int fd,char *nandp);//注册
int logon(int fd,char *nandp,char **username);//登陆
int quit(char **username);//退出
int wordQuery(int fd,char *word,char *username);//查询单词
int history(int fd,char *username);//查询历史记录
char *format(char *buf,char *data,int size);//中英混杂格式对齐
#endif
ser.c
#include "ser.h"
extern struct sockaddr_in clis[1024];//存放地址信息
extern sqlite3 *db;
char *usersname[128] = {NULL};//存放已经登录的用户名
int importDict()
{
FILE *fdict = fopen("./dict.txt","r");
if(fdict == NULL)
{
ERR_MSG("fopen");
return -1;
}
char word[128] = "";
char *mean = word;
char *errmsg = NULL;
while(fgets(word,sizeof(word),fdict))
{
while(1)
{
if(*mean == ' '&&*(mean+1) == ' ') break;
mean++;
}
*mean++ = '\0';
while(*mean == ' ') mean++;
mean[strlen(mean)-1] = '\0';
char dict[192] = "";
snprintf(dict,sizeof(dict),"insert into dict values(\"%s\",\"%s\")",word,mean);
//printf("%s\n",dict);
if(sqlite3_exec(db,dict,NULL,NULL,&errmsg) != SQLITE_OK)
{
fprintf(stderr,"sqlinsertdict:%s line:%d",errmsg,__LINE__);
return -1;
}
bzero(word,sizeof(word));
mean = word;
}
fclose(fdict);
return 0;
}
void *dictSystem(void *arg)//线程体
{
int fd = *(int *)arg;
char * username = NULL;
while(1)
{
char buf[129] = "";
ssize_t res = recv(fd,buf,sizeof(buf),0);
if(res == 0)
{
printf("[%s:%d] %d 客户端已下线\n",inet_ntoa(clis[fd].sin_addr),
ntohs(clis[fd].sin_port),fd);
break;
}
else if(res < 0)
{
ERR_MSG("recv");
break;
}
switch(buf[0])
{
case REGISTER:
dictRegister(fd,&buf[1]);
break;
case LOGON:
logon(fd,&buf[1],&username);
break;
case WORDQUERY:
wordQuery(fd,&buf[1],username);
break;
case HISTORY:
history(fd,username);
break;
case QUIT:
quit(&username);
break;
}
}
if(username != NULL) quit(&username);
close(fd);
return NULL;
}
int history(int fd,char *username)
{
int row=0,col=0;
char **result = NULL;
char *errmsg = NULL;
char buf[192] = "";
snprintf(buf,sizeof(buf),"select h.user,h.word,d.mean,h.time "
"from dict as d,history as h where h.user = '%s' and "
"d.word = h.word",username);
sqlite3_get_table(db,buf,&result,&row,&col,&errmsg);
bzero(buf,sizeof(buf));
buf[0] = 1;
if(row == 0)
{
strcpy(buf+1,"没有历史记录");
//printf("%s\n",buf+1);
send(fd,buf,sizeof(buf),0);
}
else
{
for(int i=0;i<=row;i++)
{
/*
snprintf(buf+1,sizeof(buf)-1,"%-16s%-16s%-32s%-s",result[col*i],
result[col*i+1],result[col*i+2],result[col*i+3]);
*/
char *p = buf+1;
p = format(p,result[col*i],16);
p = format(p,result[col*i+1],16);
p = format(p,result[col*i+2],32);
p = format(p,result[col*i+3],0);
send(fd,buf,sizeof(buf),0);
bzero(buf+1,sizeof(buf)-1);
}
}
sqlite3_free_table(result);
buf[0]=0;
send(fd,buf,1,0);
return 0;
}
char *format(char *buf,char *data,int size)
{
ssize_t len = strlen(data);
char *p = buf;
int count = 0;
for(int i=0;data[i]!=0;i++,p++)
{
if((*p = data[i]) < 0) count++;
}
count /= 3;
for(int i=0;i<size-len+count;i++,p++)
{
*p = ' ';
}
*p = 0;
return p;
}
int wordQuery(int fd,char *word,char *username)
{
char sql[128] = "";
snprintf(sql,sizeof(sql),"select * from dict where word = '%s'",word);
int row = 0,col = 0;
char **result = NULL;
char *errmsg = NULL;
if(sqlite3_get_table(db,sql,&result,&row,&col,&errmsg) != SQLITE_OK)
{
fprintf(stderr,"sqlselectdict:%s line:%d",errmsg,__LINE__);
return -1;
}
char msg[129] = "";
if(row == 0) strcpy(msg,"没有查询到数据");
else
{
snprintf(msg,sizeof(msg),"%s\t%s",result[2],result[3]);
//记录历史记录
time_t sys_time;
time(&sys_time);
struct tm *t = localtime(&sys_time);
char time[64]="";
snprintf(time,sizeof(time),"%4d-%02d-%02d %02d:%02d:%02d",
t->tm_year+1900,t->tm_mon+1,t->tm_mday,
t->tm_hour,t->tm_min,t->tm_sec);
snprintf(sql,sizeof(sql),"insert into history values('%s','%s','%s')",
username,word,time);
printf("%s\n",sql);
if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK)
{
fprintf(stderr,"sqlinserthistory:%s line:%d",errmsg,__LINE__);
return -1;
}
}
sqlite3_free_table(result);
if(send(fd,msg,strlen(msg),0) < 0)
{
ERR_MSG("send");
return -1;
}
return 0;
}
int quit(char **username)
{
int i = 0;
while(usersname[i] == *username) i++;//删除保存的登录的用户
while(usersname[i] != NULL) usersname[i] = usersname[++i];
free(*username);
*username = NULL;
return 0;
}
int logon(int fd,char *nandp,char **username)
{
char name[64] = "";
strcpy(name,nandp);
char sql[192] = "";
snprintf(sql,sizeof(sql),"select *from users where user = \"%s\"",name);
int row = 0,col = 0;
char **result = NULL;
char *errmsg = NULL;
if(sqlite3_get_table(db,sql,&result,&row,&col,&errmsg) != SQLITE_OK)
{
fprintf(stderr,"sqlselectusers:%s line:%d",errmsg,__LINE__);
return -1;
}
//printf("%d %d %s\n",row,col,result[0]);
if(row == 0)//判断用户名是否存在
{
sqlite3_free_table(result);
char mes = -1;
send(fd,&mes,sizeof(mes),0);
return 0;
}
char pwd[64] = "";
strcpy(pwd,nandp+strlen(nandp)+1);
if(strcmp(pwd,result[3]))
{
sqlite3_free_table(result);
char mes = -1;
send(fd,&mes,sizeof(mes),0);
return 0;
}
sqlite3_free_table(result);
int i = 0;
char mes = 0;
while(usersname[i]!=NULL)//判断用户是否已经登陆
{
if(strcmp(usersname[i],name) == 0)
{
mes = -2;
send(fd,&mes,sizeof(mes),0);
return 0;
}
i++;
}
*username = malloc(strlen(name)+1);//保存用户
strcpy(*username,name);
usersname[i] = *username;
if(send(fd,&mes,sizeof(mes),0) < 0)
{
ERR_MSG("send");
return -1;
}
return 0;
}
int dictRegister(int fd,char *nandp)
{
char name[64] = "";
strcpy(name,nandp);
char sql[192] = "";
snprintf(sql,sizeof(sql),"select *from users where user = \"%s\"",name);
int row = 0,col = 0;
char **result = NULL;
char *errmsg = NULL;
if(sqlite3_get_table(db,sql,&result,&row,&col,&errmsg) != SQLITE_OK)
{
fprintf(stderr,"sqlselectusers:%s line:%d",errmsg,__LINE__);
return -1;
}
//printf("%d %d %s\n",row,col,result[0]);
sqlite3_free_table(result);
if(row != 0)//判断用户名是否存在
{
char *mes = "用户名已存在";
send(fd,mes,strlen(mes)+1,0);
return 0;
}
char pwd[64] = "";
strcpy(pwd,nandp+strlen(nandp)+1);
bzero(sql,sizeof(sql));
snprintf(sql,sizeof(sql),"insert into users values(\"%s\",\"%s\")",name,pwd);
if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK)
{
fprintf(stderr,"sqlinsertusers:%s line:%d",errmsg,__LINE__);
return -1;
}
char *mes = "注册成功";
if(send(fd,mes,strlen(mes)+1,0) < 0)
{
ERR_MSG("send");
return -1;
}
return 0;
}
客户端
main.c
#include "cli.h"
int main(int argc,const char *argv[])
{
int cfd = socket(AF_INET, SOCK_STREAM, 0);
if(cfd < 0)
{
ERR_MSG("socket");
return -1;
}
struct sockaddr_in sin = {AF_INET,htons(PORT),inet_addr(IP)};
if(connect(cfd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
{
ERR_MSG("connect");
return -1;
}
printf("连接客户端成功\n");
while(1)
{
puts("1.注册\n2.登陆\n3.退出\n");
printf("输入:");
char flag;
scanf("%hhd",&flag);
if(flag == 3) break;
switch(flag)
{
case 1:
dictRegister(cfd);
break;
case 2:
logon(cfd);
break;
}
}
close(cfd);
return 0;
}
cli.h
#ifndef __CLI_H__
#define __CLI_H__
#include <myhead.h>
#define IP "192.168.125.106"
#define PORT 8888
#define REGISTER 1
#define LOGON 2
#define WORDQUERY 3
#define HISTORY 4
#define QUIT 5
int dictRegister(int cfd);//注册
int logon(int cfd);//登录
int dictsystem(int cfd);//系统界面
int wordQuery(int cfd);//查询单词
int quit(int cfd);//退出登录
int history(int cfd);//查询历史记录
#endif
cli.c
#include "cli.h"
int dictRegister(int cfd)
{
char buf[129] = "";
buf[0] = REGISTER;
printf("\n注册\n输入用户名:");
while(getchar()!='\n');
fgets(buf+1,sizeof(buf)-1,stdin);
buf[strlen(buf)-1] = '\0';
char *pwd = buf+strlen(buf)+1;
printf("输入密码:");
fgets(pwd,sizeof(buf)-strlen(buf)-1,stdin);
pwd[strlen(pwd)-1] = '\0';
if(send(cfd,buf,sizeof(buf),0) < 0)
{
ERR_MSG("send");
return -1;
}
bzero(buf,sizeof(buf));
ssize_t res = recv(cfd,buf,sizeof(buf),0);
if(res < 0)
{
ERR_MSG("res");
return -1;
}
else if(res == 0)
{
printf("客户端下线\n");
return -1;
}
printf("\n%s\n\n",buf);
return 0;
}
int logon(int cfd)
{
char buf[129] = "";
buf[0] = LOGON;
printf("\n登陆\n输入用户名:");
while(getchar()!='\n');
fgets(buf+1,sizeof(buf)-1,stdin);
buf[strlen(buf)-1] = '\0';
char *pwd = buf+strlen(buf)+1;
printf("输入密码:");
fgets(pwd,sizeof(buf)-strlen(buf)-1,stdin);
pwd[strlen(pwd)-1] = '\0';
if(send(cfd,buf,sizeof(buf),0) < 0)
{
ERR_MSG("send");
return -1;
}
bzero(buf,sizeof(buf));
ssize_t res = recv(cfd,buf,sizeof(buf),0);
if(res < 0)
{
ERR_MSG("res");
return -1;
}
else if(res == 0)
{
printf("客户端下线\n");
return -1;
}
if(buf[0] == -1)
{
printf("\n登陆失败,用户名或密码错误\n\n");
return 0;
}
else if(buf[0] == 0)
{
printf("\n登陆成功\n\n");
dictsystem(cfd);
return 0;
}
else if(buf[0] == -2)
{
printf("\n用户已登录,不能重复登录\n\n");
return 0;
}
return 0;
}
int dictsystem(int cfd)
{
while(1)
{
puts("1.查询单词\n2.查询历史记录\n3.退出登录\n");
printf("输入:");
char flag;
scanf("%hhd",&flag);
if(flag == 3)
{
quit(cfd);
break;
}
switch(flag)
{
case 1:
wordQuery(cfd);
break;
case 2:
history(cfd);
break;
}
}
puts("");
}
int history(int cfd)
{
puts("");
char buf[192]="";
buf[0] = HISTORY;
if(send(cfd,buf,1,0) < 0)
{
ERR_MSG("send");
return -1;
}
while(1)
{
bzero(buf,sizeof(buf));
ssize_t res = recv(cfd,buf,sizeof(buf),0);
if(res < 0)
{
ERR_MSG("res");
return -1;
}
else if(res == 0)
{
printf("客户端下线\n");
return -1;
}
if(buf[0]==1) printf("%s\n",buf+1);
else if(buf[0]==0) break;
}
puts("");
return 0;
}
int quit(int cfd)
{
char msg = QUIT;
if(send(cfd,&msg,sizeof(msg),0) < 0)
{
ERR_MSG("send");
return -1;
}
return 0;
}
int wordQuery(int cfd)
{
puts("");
char buf[129] = "";
buf[0] = WORDQUERY;
printf("输入要查询的单词:");
while(getchar()!='\n');
char *word = buf + 1;
fgets(word,sizeof(buf)-1,stdin);
int i = 0;
word[strlen(word)-1] = '\0';
while(word[i]!='\0')
{
if(word[i]=='\'')
{
for(int j = strlen(word);i!=j;j--)
word[j] = word[j-1];
i++;
}
i++;
}
if(send(cfd,buf,sizeof(buf),0) < 0)
{
ERR_MSG("send");
return -1;
}
bzero(buf,sizeof(buf));
ssize_t res = recv(cfd,buf,sizeof(buf),0);
if(res < 0)
{
ERR_MSG("res");
return -1;
}
else if(res == 0)
{
printf("客户端下线\n");
return -1;
}
printf("%s\n\n",buf);
return 0;
}