TCP網(wǎng)絡(luò)詞典
一、安裝sqlite庫
在終端輸入 sudo apt-get install sqlite3進(jìn)行安裝
安裝完成后,輸入sqlite3-version查看安裝好的版本
二、創(chuàng)建一個服務(wù)器客戶端共用的結(jié)構(gòu)體。
typedef struct
{
? ? int type;
? ? char name[N];
? ? char data[256];
}MSG;
三、搭建客戶端(封裝函數(shù)實現(xiàn)客戶端的多個功能)
①主函數(shù)搭建TCP客戶端,
int sockfd定義一個文件描述符。
if(argc!=3)//判斷輸入格式是否正確
{
printf("%s pls input serverip port\n",argv[0]);
return -1;
}
//創(chuàng)建流式套接字
if((sockfd=socket(AF_INET,SOCK_STREAM,0)<0)
{
?perror(“創(chuàng)建套接字失敗”);
return -1;
}
//網(wǎng)絡(luò)信息填充
bzero(&serveraddr,sizeof(serveraddr));
severaddr.sin_family =AF_INET;
severaddr.sin_addr.s_addr =inet_addr(argv[1]);
serveraddr.sin_port =htons(atoi(argv[2]));
//連接服務(wù)器
if(connect(sockfd,(struct sockaddr *)&serveraddr,sizeof(severaddr)<0)
{
perror("連接失敗");
return -1;
}
②搭建客戶端功能界面(可以自己設(shè)置好看點的界面)
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;//登錄成功跳轉(zhuǎn)二級菜單
break;
case 3:
close(sockfd)//關(guān)閉文件描述符退出
exit(0);
break;
default:
printf("輸入錯誤請重新輸入\n");
? ? ?}
}
③實現(xiàn)注冊功能(封裝一個函數(shù)實現(xiàn)注冊功能)
int do_register(int sockfd,MSG *msg)//文件描述符,傳輸結(jié)構(gòu)體
{
msg->type =R;//R定義在頭文件 表示用戶需要注冊功能
printf("input id:");
scanf("%s",msg->name);
getchar();
printf("pls input password:");
scanf("%s",msg->data);
if(send(sockfd,msg,sizeof(MSG),0)<0)
{
? printf("發(fā)送失敗\n");
?return -1;
}
if(recv(sockfd,msg,sizeof(MSG),0)<0)
{
printf("接收失敗\n");
return -1;
}
printf("%s\n",msg->data);
return 0;
}
④實現(xiàn)登錄功能
int do_login(int sockfd,MSG*msg)
{
msg->type =L;
printf("pls input id:");
scanf("%s",msg->name);
getchar();
printf("pls input password:");
scanf("%s",msg->data);
if(send(sockfd,msg,sizeof(MSG),0)<0)
{
printf("發(fā)送失敗\n");
return -1;
}
if(recv(sockfd,msg,sizeof(MSG),0)<0)
{
printf("接收失敗\n");
return -1;
}
if(strncmp(msg->data,""ok",3)==0)
printf("登錄成功\n");
return 1;
}
else
{
printf("%s",msg->data);
? ? ?}
return 0;
}
⑤創(chuàng)建二級菜單
next:
? while(1)
{
printf("************************************************************\n");
printf("*******1查詢*****2歷史記錄*******3退出*****************\n");
printf("************************************************************\n");
printf("************************************************************\n");
printf("pls 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");
? ? ? ?}
}
⑥實現(xiàn)查詢功能
int do_query(int sockfd,MSG*msg)
{
msg->type =Q;
while(1)
{
printf("pls input word:");
scanf("%s",msg->data);
getchar();
if(strncmp(msg->data,"#",1)==0)//輸入#退出到上一級菜單
break;
if(send(sockfd,msg,sizeof(MSG),0)<0)
{
printf("發(fā)送失敗\n");
return -1;
}
if(recv(sockfd,msg,sizeof(MSG),0)<0)
{
printf("接收失敗\n");
return -1;
}
return 0;
}
⑦時間查詢歷史記錄功能
int do_history(int sockdf,MSG*msg)
{
msg->type=H;
send(sock,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;
}
三\創(chuàng)建TCP服務(wù)器
①打開數(shù)據(jù)庫
在數(shù)據(jù)庫的當(dāng)前路徑下創(chuàng)建一個名為word.txt的文件 文件中存放單詞導(dǎo)入到詞庫.
if(sqlite3_open(DATABASE,&db)!=SQLITE_OK)
{
printf("%s\n",sqlite3_errmsg(db));
return -1;
}
else
printf("open DATABASE success\n");
②搭建TCP服務(wù)器
創(chuàng)建流式套接字
if((sockfd=socket(AF_INET,SOCK_STREAM,0)<0)
{
perror("faill to socket");
return -1;
}
填充網(wǎng)絡(luò)信息
bzero(&serveraddr,sizeof(serveraddr));
severaddr.sin_family =AF_INET;
serveraddr.sin_addr.s_addr=inet_addr(argv[1]);
severaddr.sin_port=htons(atoi(argv[2]));
bind綁定
if(bind(sockfd,(struct sockaddr *)&serveraddr,sizeof(serveraddr))<0)
{
perror("fail to bind\n");
return -1;
}
將套接字設(shè)置為監(jiān)聽 等待客戶端鏈接
if(listen(sockfd,5)<0)
{
printf("fail to listen\n");
return -1;
}
②創(chuàng)建一級菜單
while(1)
{
if((acceptfd=accept(sockfd,NULL,NULL))<0)
{
perror("fail to accept");
return -1;
}
//創(chuàng)建父子進(jìn)程
if((pid=fork())<0)
{
perror("fail to fork");
return -1;
}
else if(pid==0)
{
close(sockfd);
do_cilent(acceptfd,db);
}
else?
?{
close(acceptfd);
? }
}
③ 注冊功能
void do_register(int acceptfd,MSG*msg,sqlite3*db)
{
char*errmsg;
char sql[128];
//創(chuàng)建表格
char sql1[128]="create table if not exists usr(id char,password char)";
char *errmsg1=NULL;
if(sqlite3_exec(db,sql1,NULL,NULL,&errmsg1)!=SQLITE_OK)
{
printf("sqlite3_exec failed:%s_%d_\n",errmsg1,_LINE_);
return;
}
printf("create table dict success _&d_\n",_LINE_);
sprintf("%s\n",errmsg);
strcpy(msg->data,,"usr name already exist");
else
{
printf("cilent register ok!\n");
strcpy(msg->data,"ok!");
}
if(send(acceptfd,msg,sizeof(MSG),0)<0)
? ?{?
perror("發(fā)送失敗\n");
return;
? ?}
return;
}
④登錄功能
int do_login(int acceptfd,MSG*msg,sqlite3*db)
{
char sql[128]={};
char *errmsg;
int nrow;
int ncloumn;
char **resultp;
sprintf(sql,"select *from usr whrer id='%s' and password ='%s';",msg->name,msg->data);
printf("%s\n",sql);
if(sqlite3_get_table(db,sql,&resulyp,&nrow,&ncloumn,&errmsg)!=SQLITE_OK)
{
printf("%s\n",errmsg);
return -1;
}
else
{
printf("get table ok\n");
}
//庫里面如果存儲了改用戶的信息,跳轉(zhuǎn)到二級界面 登錄成功
if(nrow==1)
{
strcpy(msg->data,"OK");
send(acceptfd,msg,sizeof(MSG),0);
return -1;
}
if(nrow==0)
? ? ?{
strcpy(msg->data,"用戶或者密碼錯誤\n");
send(acceptfd,msg,sizeof(MSG),0);
return 0;
? ? ?}
return 0;
}
⑤單詞比對功能
int do_searchword(int acceptfd,MSG*msg,char word[])
{
FILE*fp;
int len=0;
char temp[512];
int result;
char *p
if((fp=fopen("word.txt","r")==NULL)
{
perror("fail to fopen\n");
strcpy(msg->data,"打開詞庫失敗\n");
send(acceptfd,msg,sizeof(MSG),0);
return -1;
}
len =strlen(word);
printf("%s",len=%d\n",word,len);
while(fgets(temp,512,fp)!=NULL)
{
printf("%s\n",temp);
result=strncmp(temp,word,len);
if(result>0)
{
continue;
}
if(result<0||temp[len]!=' ');
{
break;
}
else{
printf("已經(jīng)找到單詞\n");
p=temp+len;
while(*p=='? ')//把空格去掉
{
p++;
}
strncpy(msg->data,p);
printf("%s\n",msg->data);
send(acceptfd,msg,sizeof(MSG),0);
fclose(fp);
return 1;
? }
}
fclose(fp);
return 0;
}
⑥獲取時間函數(shù)
int get_date(char *date)
{
time_t t;
struct tm*tp;
time(&t);
tp=loctaltime(&t);
sprintf(data,"%d-%d-%d %d:%d:%d",tp->tm_year+1990,tp->tm_mon+1,tp->mday,tp->tm_hour,tp->tm_min,tp->sec);
return 0;
}
⑦查詢單詞功能
int do_query(int acceptfd,MSG*msg,sqlite3*db)
{
char word[128];
int found=0;
char data[128];
char sql[128];
char *errmsg;
strcpy(word,msg->data);
found = do_searchword(acceptfd,msg,word);
char sql1[128]="create table if not exists recode(id char,word,char,mean char,time int);";
char *errmsg1=NULL;
if(sqlite3_exec(db,sql1,NULL,NULL,&errmsg1,_LINE_)!=SQLITE_OK)
{
printf("sqlite3_exec failed:%s _%d_\n",errmsg1,_LINE_);
return -1;
}
sprintf(sql1,"sqlect *from record where name= %s";,msg->name);
if(found==1)
{
get_data(date);
sprintf(sql,"insert into record valuse('%s','%s','%s')",msg->name,data,word);
printf("%s\n",sql);
if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
{
printf("%s\n",errmsg);
return -1;
? }
}
else
{
strcpy(msg->data,"not found!");
}
send(acceptfd,msg,sizeof(MSG),0);
return? 0;
}
⑧查詢歷史
int do_histroty(int acceptfd,MSG*msg,sqlite3*db)
{
char sql[128]={};
char *errmsg;
if(sqlite3_exec(db,sql,history_callback,(void*)&acceptfd,&errmsg)!=SQLITE_OK)
printf("%s\n",errmsg);
else
{
printf("%s\n",errmsg);
}
else
printf("quety record done\n");
msg->data[0]='\0';
send(acceptfd,msg,sizeof(MSG),0);
rerurn 0;
}
⑨得到查詢結(jié)果 發(fā)送給客戶端
int history_callback(void*arg,int f_num,char **f_value,char **f_name)
{
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_client(int acceptfd,sqlite3*db)
{
MSG msg;
while("type:%d\n",msg.type);
{
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");
}
}