客户端
client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#define N 32
#define R 1 //register
#define L 2 //login
#define Q 3 //query
#define H 4 //history
typedef struct{
int type;
char name[N];
char data[128];
}MSG;
//functions
int do_register(int sockfd, MSG *msg)
{
msg->type = R;
printf("Input name:");
scanf("%s", msg->name);
getchar();
printf("Input password:");
scanf("%s", msg->data);
getchar();
if(send(sockfd, msg, sizeof(MSG), 0) < 0)
{
printf("send failed!\n");
return -1;
}
if(recv(sockfd, msg, sizeof(MSG), 0) < 0)
{
printf("recv failed!\n");
return -1;
}
//ok or already exist
printf("%s\n", msg->data);
}
int do_login(int sockfd, MSG *msg)
{
msg->type = L;
printf("Input name:");
scanf("%s", msg->name);
getchar();
printf("Input password:");
scanf("%s", msg->data);
getchar();
if(send(sockfd, msg, sizeof(MSG), 0) < 0)
{
printf("send failed!\n");
return -1;
}
if(recv(sockfd, msg, sizeof(MSG), 0) < 0)
{
printf("recv failed!\n");
return -1;
}
if(strncmp(msg->data, "ok", 3) == 0)
{
printf("Login ok!\n");
return 1;
}
else{
printf("%s",msg->data);
}
return 0;
}
int do_query(int sockfd, MSG *msg)
{
msg->type = Q;
puts("-------------");
while (1)
{
printf("Input word:");
scanf("%s", msg->data);
if(strncmp(msg->data, "#", 1) == 0)
break; //输入“#”返回上级菜单
//发送给服务器
if(send(sockfd, msg, sizeof(MSG), 0)<0){
printf("send failed!\n");
return -1;
}
//等待接受服务器返回的信息
if(recv(sockfd, msg, sizeof(MSG), 0)<0){
printf("recv failed!\n");
return -1;
}
printf("%s\n",msg->data);
}
return 0;
}
int do_history(int sockfd, MSG *msg)
{
msg->type = H;
send(sockfd, msg, sizeof(MSG), 0);
while (1)
{
recv(sockfd, msg, sizeof(MSG), 0);
if(msg->data[0] == '\0')
break;
printf("%s\n",msg->data);
}
return 0;
}
int main(int argc, char *argv[])
{
int sockfd;
int n;
struct sockaddr_in serveraddr;
MSG msg;
if(argc!=3)
{
printf("argc error!\n");
return -1;
}
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("socket failed!\n");
return -1;
}
bzero(&serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
serveraddr.sin_port = htons(atoi(argv[2]));
//connect
if(connect(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0)
{
perror("connect failed!\n");
return -1;
}
while (1)
{
printf("********************************************\n");
printf("*1.register 2.login 3.quit *\n");
printf("********************************************\n");
printf("please choose:");
scanf("%d", &n);
getchar();
switch(n)
{
case 1:
do_register(sockfd, &msg);
break;
case 2:
if(do_login(sockfd, &msg) == 1)
{
goto next;
}
break;
case 3:
close(sockfd);
exit(0);
break;
default:
printf("Invalid data cmd!\n");
break;
}
}
next:
while (1)
{
printf("********************************************\n");
printf("*1.query 2.history 3.quit *\n");
printf("********************************************\n");
printf("please choose:");
scanf("%d", &n);
getchar();
switch (n)
{
case 1:
do_query(sockfd, &msg);
break;
case 2:
do_history(sockfd, &msg);
break;
case 3:
close(sockfd);
exit(0);
break;
default:
printf("Invalid data cmd!\n");
break;
}
}
return 0;
}
服务器
server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sqlite3.h>
#include <signal.h>
#include <time.h>
#define N 32
#define R 1 //register
#define L 2 //login
#define Q 3 //query
#define H 4 //history
#define DATABASE "my.db"
typedef struct{
int type;
char name[N];
char data[128];
}MSG;
//functions
int do_search(int acceptfd, MSG *msg, char word[])
{
FILE * fp;
int len;
char buf[256] = {};
int result;
char *p;
if((fp = fopen("dict.txt","r")) == NULL){
perror("fopen failed!\n");
strcpy(msg->data, "Failed to open dict.txt");
send(acceptfd, msg, sizeof(MSG), 0);
return -1;
}
len = strlen(word);
printf("%s, len = %d\n", word, len);
while(fgets(buf, 256, fp) != NULL){
result = strncmp(buf, word, len);
if(result < 0){
continue;
}
if(result > 0 || buf[len]!=' '){
break;
}
p = buf + len;
while(*p==' '){
p++; //跳过所有空格
}
strcpy(msg->data, p);
fclose(fp);
return 1;
}
fclose(fp);
return 0;
}
int get_date(char *date)
{
time_t t;
struct tm *tp;
time(&t);
tp = localtime(&t);
sprintf(date, "%d-%d-%d %d:%d:%d",tp->tm_year+1900, tp->tm_mon+1, tp->tm_mday, tp->tm_hour, tp->tm_min, tp->tm_sec);
return 0;
}
void do_register(int acceptfd, MSG *msg, sqlite3 *db)
{
char * errmsg;
char sql[256];
sprintf(sql, "insert into usr values('%s', %s);", msg->name, msg->data);
printf("%s\n",sql);
if(sqlite3_exec(db, sql, NULL, NULL, &errmsg)!=SQLITE_OK)
{
printf("%s\n",errmsg);
strcpy(msg->data, "usr name already exist!");
}
else{
printf("client register ok!\n");
strcpy(msg->data, "ok!");
}
if(send(acceptfd, msg, sizeof(MSG), 0) < 0){
perror("send failed!\n");
}
}
int do_login(int acceptfd, MSG *msg, sqlite3 *db)
{
char sql[256];
char *errmsg;
int nrow,ncloumn;
char **resultp;
sprintf(sql, "select * from usr where name = '%s' and pass = '%s';", msg->name, msg->data);
printf("%s\n",sql);
if(sqlite3_get_table(db, sql, &resultp, &nrow, &ncloumn, &errmsg)!=SQLITE_OK){
printf("login failed!\n%s\n",errmsg);
return -1;
}
else{
printf("get_table ok!\n");
}
if(nrow == 1){
strcpy(msg->data,"ok");
send(acceptfd, msg, sizeof(MSG), 0);
}
else{
strcpy(msg->data,"usr passwd wrong!\n");
send(acceptfd, msg, sizeof(MSG), 0);
}
return 0;
}
int do_query(int acceptfd, MSG *msg, sqlite3 *db)
{
char word[32];
int found;
char date[64];
char sql[256];
char *errmsg;
strcpy(word, msg->data);
if((found = do_search(acceptfd, msg, word)) == 1){ //找到了
get_date(date);
sprintf(sql, "insert into record values('%s', '%s', '%s')", msg->name, date, word);
if((sqlite3_exec(db, sql, NULL, NULL, &errmsg))!=SQLITE_OK)
{
printf("%s\n", errmsg);
return -1;
}
else{
printf("Insert record done!\n");
}
}
else{
strcpy(msg->data, "not found!");
}
//返回查询结果给客户端
send(acceptfd, msg, sizeof(MSG), 0);
return 0;
}
int history_callback(void* arg, int f_num, char** f_value, char** f_name)
{
//record: name|date|word
int acceptfd;
MSG msg;
acceptfd = *((int*)arg);
sprintf(msg.data, "%s,%s", f_value[1], f_value[2]);
send(acceptfd, &msg, sizeof(MSG), 0);
return 0;
}
int do_history(int acceptfd, MSG *msg, sqlite3 *db)
{
char sql[256]={};
char *errmsg;
sprintf(sql, "select * from record where name = '%s'",msg->name);
//查询数据库
if(sqlite3_exec(db, sql, history_callback, (void*)&acceptfd, &errmsg)!=SQLITE_OK)
{
printf("%s\n", errmsg);
}
else{
printf("Query record done.\n");
}
msg->data[0] = '\0';
send(acceptfd, msg, sizeof(MSG), 0);
return 0;
}
int do_client(int acceptfd, sqlite3 *db)
{
MSG msg;
while(recv(acceptfd, &msg, sizeof(msg), 0) > 0)
{
printf("type:%d\n",msg.type);
switch (msg.type)
{
case R:
do_register(acceptfd, &msg, db);
break;
case L:
do_login(acceptfd, &msg, db);
break;
case Q:
do_query(acceptfd, &msg, db);
break;
case H:
do_history(acceptfd, &msg, db);
break;
default:
printf("Invalid data msg!\n");
break;
}
}
printf("client exit.\n");
close(acceptfd);
exit(0);
return 0;
}
int main(int argc, char *argv[])
{
int sockfd;
int n;
struct sockaddr_in serveraddr;
MSG msg;
sqlite3 *db;
int acceptfd;
pid_t pid;
if(argc!=3)
{
printf("argc error!\n");
return -1;
}
//open database
if(sqlite3_open(DATABASE, &db)!=SQLITE_OK)
{
printf("%s\n",sqlite3_errmsg(db));
return -1;
}
else
{
printf("open DATABASE success!\n");
}
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("socket failed!\n");
return -1;
}
bzero(&serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
serveraddr.sin_port = htons(atoi(argv[2]));
//bind
if(bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0)
{
perror("bind failed!\n");
return -1;
}
//listen
if(listen(sockfd, 5) < 0)
{
perror("listen failed!\n");
return -1;
}
//deal zombie
signal(SIGCHLD, SIG_IGN);
while (1)
{
if((acceptfd = accept(sockfd, NULL, NULL)) < 0)
{
perror("accept failed!\n");
return -1;
}
if((pid = fork()) < 0)
{
perror("pid failed!\n");
return -1;
}
else if(pid == 0) //son
{
close(sockfd);
do_client(acceptfd, db);
}
else //father
{
close(acceptfd);
}
}
return 0;
}