基于TCP的在线词典
此程序主要是利用tcp传输和sqlite3进行操作的。
程序执行过程部分截图
#在终端输入sqlite3,查看是否安装sqlite3,没有的话先安装sqlite3
sudo apt-get install sqlite3
sudo apt-get install libsqlite3-dev
打开数据库 sqlite3 my.db
然后在里面创建数据库
create table <table_name> (f1 type1, f2 type2,…);
需要在编译选项上加入-lsqlite3
server.c
#include <stdlib.h>
#include <string.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <sqlite3.h>
#include <time.h>
#define N 256
typedef struct _msg
{
char types;
char name[N] ;
char text[N] ;
}msg_t;
int login_callback(void*data,int num,char**value,char**name)
{
// int i;
*(int * )data = 1 ;
#if 0
if(*flag)
{
*flag = 0 ;
for(i=0;i<num;i++)
{
printf("%-10s",name[i]);
}
printf("\n");
}
for(i=0;i<num;i++)
{
printf("%-10s",value[i]);
}
printf("\n");
#endif
return 0;
}
int process_register(int newsockfd,msg_t *msgp,sqlite3 *db)
{
int ret;
char *errmsg ;
char sqlstr[N] = {0};
sprintf(sqlstr,"insert into user values('%s','%s');",msgp->name,msgp->text);
printf("sqlstr=%s\n",sqlstr) ;
ret = sqlite3_exec(db,sqlstr,NULL,NULL,&errmsg);
if(ret != SQLITE_OK)
{
printf("sqlite3_exec:%s\n",errmsg);
strcpy(msgp->text,"用户名已经存在,请重新输入");
}
else
{
strcpy(msgp->text,"注册成功");
}
ret = write(newsockfd,msgp,sizeof(msg_t));
if(ret < 0)
{
perror("write");
exit(-1);
}
return 0;
}
int process_login(int newsockfd,msg_t *msgp,sqlite3 *db)
{
int ret;
char *errmsg ;
char sqlstr[N] = {0};
int login_flag = 0 ;
sprintf(sqlstr,"select * from user where name='%s' and passwd='%s';",msgp->name,msgp->text);
printf("sqlstr=%s\n",sqlstr) ;
ret = sqlite3_exec(db,sqlstr,login_callback,&login_flag,&errmsg);
if(ret != SQLITE_OK)
{
printf("sqlite3_exec:%s\n",errmsg);
}
if(login_flag == 1)
{
strcpy(msgp->text,"登录成功");
}
else
{
strcpy(msgp->text,"用户或密码错误,请重新输入");
}
ret = write(newsockfd,msgp,sizeof(msg_t));
if(ret < 0)
{
perror("write");
exit(-1);
}
return 0;
}
char * search_word(char *word)
{
FILE * filp;
static char line[N] ={0};
char newword[100] ;
strcpy(newword,word);
strcat(newword," ");
filp = fopen("./dict.txt","r");
if(filp == NULL)
{
perror("fopen") ;
exit(-1);
}
while( fgets(line,N,filp) != NULL )
{
if( strncmp(newword,line,strlen(newword)) == 0 )
{
printf("%s",line) ;
return line ;
}
}
return NULL;
}
char * get_localtime()
{
static char buf[100] ={0} ;
time_t tm;
time(&tm);
strcpy(buf,ctime(&tm));
buf[strlen(buf) -1] = 0 ;
return buf;
}
int process_query(int newsockfd,msg_t *msgp,sqlite3 *db)
{
int ret;
char *retp;
char *errmsg ;
char sqlstr[N] = {0};
int login_flag = 0 ;
char word[100] = {0} ;
strcpy(word,msgp->text);
retp = search_word(word);
if(retp == NULL)
{
strcpy(msgp->text,"要查找的单词不存在");
ret = write(newsockfd,msgp,sizeof(msg_t));
if(ret < 0)
{
perror("write");
exit(-1);
}
}
else
{
strcpy(msgp->text,retp);
sprintf(sqlstr,"insert into record values('%s','%s','%s');",msgp->name,word,get_localtime());
printf("sqlstr=%s\n",sqlstr) ;
ret = sqlite3_exec(db,sqlstr,NULL,NULL,&errmsg);
if(ret != SQLITE_OK)
{
printf("sqlite3_exec:%s\n",errmsg);
}
ret = write(newsockfd,msgp,sizeof(msg_t));
if(ret < 0)
{
perror("write");
exit(-1);
}
}
return 0;
}
int history_callback(void*data,int num,char**value,char**name)
{
int i,ret;
msg_t msg;
char buf[256] ={0};
int newsockfd = *(int * )data ;
memset(&msg,0,sizeof(msg_t));
msg.types = 'H' ;
for(i=0;i<num;i++)
{
sprintf(buf,"%-10s",value[i]);
strcat(msg.text,buf);
}
ret = write(newsockfd,&msg,sizeof(msg_t));
if(ret < 0)
{
perror("write");
exit(-1);
}
return 0;
}
int process_history(int newsockfd,msg_t *msgp,sqlite3 *db)
{
int ret;
char *retp;
char *errmsg ;
char sqlstr[N] = {0};
int login_flag = 0 ;
sprintf(sqlstr,"select * from record where name='%s';",msgp->name);
printf("sqlstr=%s\n",sqlstr) ;
ret = sqlite3_exec(db,sqlstr,history_callback,&newsockfd,&errmsg);
if(ret != SQLITE_OK)
{
printf("sqlite3_exec:%s\n",errmsg);
}
strcpy(msgp->text,"传输完成");
ret = write(newsockfd,msgp,sizeof(msg_t));
if(ret < 0)
{
perror("write");
exit(-1);
}
return 0;
}
// ./a.out 192.168.1.57 8000
// argv[0] argv[1] aegv[2]
int main(int argc, const char *argv[])
{
sqlite3 *db ; /* OUT: SQLite db handle */
int data = 1 ;
int sockfd,ret,newsockfd;
struct sockaddr_in myaddr,client;
signal(SIGCHLD,SIG_IGN);
msg_t msg;
if(argc != 3)
{
printf("运行程序时带入ip 和 port\n");
exit(-1);
}
socklen_t addrlen = sizeof(client);
sockfd = socket(AF_INET,SOCK_STREAM,0);
if(sockfd < 0)
{
perror("socket");
exit(-1);
}
printf("sockfd=%d\n",sockfd);
memset(&myaddr,0,sizeof(myaddr));
myaddr.sin_family = AF_INET ;
myaddr.sin_port = htons(atoi(argv[2]));
myaddr.sin_addr.s_addr = inet_addr(argv[1]);
ret = bind(sockfd,(struct sockaddr *)&myaddr,sizeof(myaddr)) ; // 给socket 一个固定的ip 和端口
if(ret < 0)
{
perror("bind");
exit(-1);
}
ret = listen(sockfd,10);
if(ret < 0)
{
perror("listen");
exit(-1);
}
if(sqlite3_open("my.db",&db) != SQLITE_OK)
{
printf("%s\n",sqlite3_errmsg(db));
exit(-1);
}
while(1)
{
newsockfd = accept(sockfd,(struct sockaddr *)&client,&addrlen) ;
if(newsockfd < 0)
{
printf("accept");
exit(-1);
}
printf("newsockfd = %d\n",newsockfd);
printf("%s and %d\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port));
if( fork() == 0)
{
while(1)
{
ret = read(newsockfd,&msg,sizeof(msg_t));
if(ret < 0)
{
printf("read");
exit(-1);
}
else if(ret == 0)
{
break ;
}
printf("msg.type=%c\n",msg.types);
switch(msg.types)
{
case 'R':
process_register(newsockfd,&msg,db);
break ;
case 'L':
process_login(newsockfd,&msg,db);
break ;
case 'Q':
process_query(newsockfd,&msg,db);
break ;
case 'H':
process_history(newsockfd,&msg,db);
break ;
default:
break ;
}
}
close(newsockfd);
exit(0);
}
close(newsockfd);
}
return 0;
}
client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define N 256
typedef struct _msg
{
char types;
char name[N] ;
char text[N] ;
}msg_t;
int process_register(int sockfd,msg_t *msgp)
{
int ret;
msgp->types = 'R';
printf("input your name:");
fgets(msgp->name,N,stdin);
msgp->name[strlen(msgp->name) -1 ] = 0 ;
printf("input your passwd:");
fgets(msgp->text,N,stdin);
msgp->text[strlen(msgp->text) -1 ] = 0 ;
ret = write(sockfd,msgp,sizeof(msg_t));
if(ret < 0)
{
perror("write");
exit(-1);
}
memset(msgp,0,sizeof(msg_t)) ;
ret = read(sockfd,msgp,sizeof(msg_t));
if(ret < 0)
{
perror("write");
exit(-1);
}
printf("%s\n",msgp->text);
return 0;
}
int process_query(int sockfd,msg_t *msgp)
{
int ret;
msgp->types = 'Q';
while(1)
{
printf("input your word:");
fgets(msgp->text,N,stdin);
msgp->text[strlen(msgp->text) -1 ] = 0 ;
if(strncmp(msgp->text,"#",1) == 0 ) break ;
ret = write(sockfd,msgp,sizeof(msg_t));
if(ret < 0)
{
perror("write");
exit(-1);
}
memset(msgp,0,sizeof(msg_t)) ;
ret = read(sockfd,msgp,sizeof(msg_t));
if(ret < 0)
{
perror("write");
exit(-1);
}
printf("%s\n",msgp->text);
}
return 0;
}
int process_history(int sockfd,msg_t *msgp)
{
int ret;
msgp->types = 'H';
ret = write(sockfd,msgp,sizeof(msg_t));
if(ret < 0)
{
perror("write");
exit(-1);
}
memset(msgp,0,sizeof(msg_t)) ;
while(1)
{
ret = read(sockfd,msgp,sizeof(msg_t));
if(ret < 0)
{
perror("write");
exit(-1);
}
if(strncmp(msgp->text,"传输完成",sizeof("传输完成")) == 0) break ;
printf("%s\n",msgp->text);
}
return 0;
}
int process_login(int sockfd,msg_t *msgp)
{
int ret,num;
msgp->types = 'L';
printf("input your name:");
fgets(msgp->name,N,stdin);
msgp->name[strlen(msgp->name) -1 ] = 0 ;
printf("input your passwd:");
fgets(msgp->text,N,stdin);
msgp->text[strlen(msgp->text) -1 ] = 0 ;
ret = write(sockfd,msgp,sizeof(msg_t));
if(ret < 0)
{
perror("write");
exit(-1);
}
memset(msgp,0,sizeof(msg_t)) ;
ret = read(sockfd,msgp,sizeof(msg_t));
if(ret < 0)
{
perror("write");
exit(-1);
}
printf("%s\n",msgp->text);
if(strncmp(msgp->text,"登录成功",sizeof("登陆成功")) == 0 )
{
while(1)
{
printf("*************************************************\n");
printf("*1:search word 2: history 3: quit************\n");
printf("*************************************************\n");
printf("please input your choice >:");
scanf("%d",&num);
scanf("%*[^\n]");scanf("%*c"); //回收残留在标准输入的字符
switch(num)
{
case 1:
process_query(sockfd,msgp);
break ;
case 2:
process_history(sockfd,msgp);
break ;
case 3:
close(sockfd);
exit(0);
default:
break ;
}
}
}
return 0;
}
// ./a.out 192.168.1.57 8000
int main(int argc, const char *argv[])
{
char buf[N] = {0};
int sockfd,ret,newsockfd;
int num;
struct sockaddr_in server,client;
msg_t msg;
if(argc != 3)
{
printf("运行程序时带入ip 和 port\n");
exit(-1);
}
socklen_t addrlen = sizeof(client);
sockfd = socket(AF_INET,SOCK_STREAM,0);
if(sockfd < 0)
{
perror("socket");
exit(-1);
}
printf("sockfd=%d\n",sockfd);
memset(&msg,0,sizeof(msg));
memset(&server,0,sizeof(server));
server.sin_family = AF_INET ;
server.sin_port = htons( atoi(argv[2]) );
server.sin_addr.s_addr = inet_addr(argv[1]);
ret = connect(sockfd,(struct sockaddr *)&server,sizeof(server)) ;
if(ret < 0)
{
perror("connect");
exit(-1);
}
while(1)
{
printf("*************************************************\n");
printf("*1:register 2: login 3: quit****************\n");
printf("*************************************************\n");
printf("please input your choice >:");
scanf("%d",&num);
scanf("%*[^\n]");scanf("%*c"); //回收残留在标准输入的字符
switch(num)
{
case 1:
process_register(sockfd,&msg);
break ;
case 2:
process_login(sockfd,&msg);
break ;
case 3:
close(sockfd);
exit(0);
default:
break ;
}
}
printf(">:");
fgets(buf,N,stdin);
ret = write(sockfd,buf,N) ;
if(ret < 0)
{
perror("write");
exit(-1);
}
ret = read(sockfd,buf,N);
if(ret < 0)
{
printf("read");
exit(-1);
}
printf("%s\n",buf);
close(sockfd);
return 0;
}
运行时gcc server.c -o server -lsqlite3
./server 本机ip 端口号
gcc client.c -o client -lsqlite3
./client 本机ip 端口号
此外还需要个词典的文件 。自行解决。