项目要求
服务器:
所需头文件:linklist.h SerOperation.h
所需源文件:linklist.c SerOperation.c
主函数源文件:Ser.c
linklist.h:
#ifndef __LINKLIST_H__
#define __LINKLIST_H__#include
#include
#include
}linkList;linkList *list_creat();linkList *node_buy(char *str);int list_empty(linkList *h);int list_insert_head(linkList *h,char *str);int list_delete(linkList *h,char *str);int list_delete_head(linkList *h);int list_destroy(linkList *h);#endif
SerOperation.h:
#ifndef __SEROPERATION_H__
#define __SEROPERATION_H__#include
#include
#include
#include "./linklist.h"
#include
#include
#include
#include
#include
#include
}while(0)//创建数据库
sqlite3 *create_database();//删除表
int drop_table();//关闭数据库
int close_database(sqlite3 *db);//单词导入数据库--数据库操作
int import_words(sqlite3 *db);//用户注册--数据库操作
int user_register(sqlite3 *db,char *username,char *password,char *dest);//用户登录--数据库操作
int user_login(sqlite3 *db,char *username,char *password,char *dest);//查询单词--数据库操作
linkList *select_word(sqlite3 *db,char *word,char *username);//记录历史查询信息--数据库操作
int insert_history(sqlite3 *db,char *word,char *username,linkList *head);//查看历史查询信息--数据库操作
linkList *select_history(sqlite3 *db,char *username);//处理接收到的客户端消息
int deal_rcvmsg(char *rcvmsg);//处理客户端的注册请求
int do_register(int newfd,sqlite3 *db,char *rcvmsg);//修改用户状态为在线
int update_state_online(sqlite3 *db,char *username);//修改用户状态为离线
int update_state_offline(sqlite3 *db,char *username);//处理客户端的登录请求
int do_login(int newfd,sqlite3 *db,char *rcvmsg);//处理客户端的查询单词请求
int do_select_world(int newfd,sqlite3 *db,char *username,char *rcvmsg);//处理客户端的查看历史信息请求
int do_select_history(int newfd,sqlite3 *db,char *username);//减少TCP的粘包问题
int writen(int fd,char *msg,int size);
int mysendMsg(int fd,char *msg,int size);
int readn(int fd,char *msg,int size);
int myrecvMsg(int fd,char **msg);#endif
linklist.c:
#include "linklist.h"//头节点的创建
linkList *list_creat()
{linkList *h=(linkList *)malloc(sizeof(linkList));if(NULL==h){return NULL;}h->next=NULL;return h;
}//申请节点
linkList *node_buy(char *str)
{linkList *p=(linkList *)malloc(sizeof(linkList));if(NULL==p){return NULL;}strcpy(p->msg,str);p->next=NULL;return p;
}//判空
int list_empty(linkList *h)
{if(NULL==h){return -1;}return h->next==NULL ? 1 : 0;
}//头插法
int list_insert_head(linkList *h,char *str)
{if(NULL==h){return -1;}linkList *l=node_buy(str);if(NULL==l){return -2;}l->next=h->next;h->next=l;return 0;
}//删除目标
int list_delete(linkList *h,char *str)
{if(NULL==h){return -1;}if(list_empty(h)){return -2;}linkList *p=h->next;while(p->next!=NULL){if(strcmp(p->msg,str)==0)break;elsep=p->next;}while(h->next!=p){h=h->next;}h->next=p->next;free(p);return 0;
}//头删
int list_delete_head(linkList *h)
{if(NULL==h){return -1;}if(!list_empty(h)){linkList *p=h->next;h->next=p->next;free(p);}else{return -1;}return 0;
}//销毁链表
int list_destroy(linkList *h)
{while(list_delete_head(h)==0);free(h);h=NULL;return 0;
}
SerOperation.c:
#include "./SerOperation.h"//创建数据库
sqlite3 *create_database()
{sqlite3 *db=NULL;char *msg=NULL;char buf[128]="";if(sqlite3_open("./SerDB.db",&db)!=SQLITE_OK){ERR_MSG("create database fail",sqlite3_errmsg(db));return NULL;}//创建存储用户信息表格及在线状态bzero(buf,sizeof(buf));sprintf(buf,"create table if not exists usermsg (username char primary key,password char,state char)");if(sqlite3_exec(db,buf,NULL,NULL,&msg)!=SQLITE_OK){ERR_MSG("create usermsg table fail",msg);return NULL;}//创建四级单词存储表格bzero(buf,sizeof(buf));sprintf(buf,"create table if not exists wordsmsg (word char,annotation char)");if(sqlite3_exec(db,buf,NULL,NULL,&msg)!=SQLITE_OK){ERR_MSG("create wordsmsg table fail",msg);return NULL;}fprintf(stdout,"create database success\n");return db;
}//删除单词的表,防止服务器重启时重复导入单词
int drop_table()
{sqlite3 *db=NULL;char *msg=NULL;char buf[128]="";if(sqlite3_open("./SerDB.db",&db)!=SQLITE_OK){ERR_MSG("open database fail",sqlite3_errmsg(db));return -1;}bzero(buf,sizeof(buf));sprintf(buf,"drop table wordsmsg");if(sqlite3_exec(db,buf,NULL,NULL,&msg)!=SQLITE_OK){ERR_MSG("drop table fail",msg);return -1;}close_database(db);db=NULL;return 0;
}//关闭数据库
int close_database(sqlite3 *db)
{if(sqlite3_close(db)!=SQLITE_OK){ERR_MSG("close database fail",sqlite3_errmsg(db));return -1;}fprintf(stdout,"close database success\n");return 0;
}//单词导入数据库--数据库操作
int import_words(sqlite3 *db)
{char *msg=NULL;char *ch;int i=0;char buf[128]="";char str[64]="";char word[32]="";char mean[32]="";FILE *fd=fopen("./dict.txt","r");if(fd==NULL){perror("fopen fail");return -1;}while(1){bzero(word,sizeof(word));bzero(mean,sizeof(mean));bzero(str,sizeof(str));i=0;if(fgets(str,sizeof(str),fd)==NULL){break;}str[strlen(str)-1]='\0';ch=str+i;while(*ch!='\0'){if(*ch==' ' && *(ch+1)==' '){break;}i++;ch=str+i;}str[i]='\0';strcpy(word,str);strcpy(mean,str+i+3);sprintf(buf,"insert into wordsmsg values (\"%s\",\"%s\")",word,mean);if(sqlite3_exec(db,buf,NULL,NULL,&msg)!=SQLITE_OK){ERR_MSG("import word fail",msg);return -1;}}fclose(fd);fprintf(stdout,"import words success\n");
}//用户注册--数据库操作
int user_register(sqlite3 *db,char *username,char *password,char *dest)
{char *msg=NULL;char buf[128]="";char src[64]="";char state[]="offline";int len=0;sprintf(buf,"insert into usermsg values (\"%s\",\"%s\",\"%s\")",username,password,state);if(sqlite3_exec(db,buf,NULL,NULL,&msg)!=SQLITE_OK){sprintf(src,"register fail : username is exists!");len=strlen(src);strcpy(dest,src);return len;}sprintf(src,"register success!");len=strlen(src);strcpy(dest,src);return len;
}//用户登录--数据库操作
int user_login(sqlite3 *db,char *username,char *password,char *dest)
{char buf[128]="";char src[64]="";char *msg=NULL;char **restr=NULL;int len=0;int row=0;int column=0;sprintf(buf,"select * from usermsg where username=\"%s\"",username);if(sqlite3_get_table(db,buf,&restr,&row,&column,&msg)!=SQLITE_OK){ERR_MSG("get usermsg fail",msg);return -1;}if(row==0){sprintf(src,"login fail : username inexistence!");len=strlen(src);strcpy(dest,src);}else{if(strcmp(restr[4],password)==0){if(strcmp(restr[5],"offline")==0){sprintf(src,"login success!");len=strlen(src);strcpy(dest,src);bzero(buf,sizeof(buf));//登录成功,创建一个以用户名命名的表,用来存储用户历史查询信息sprintf(buf,"create table if not exists %s (word char,annotation char,time char)",username);if(sqlite3_exec(db,buf,NULL,NULL,&msg)!=SQLITE_OK){ERR_MSG("create historymsg table fail",msg);return -1;}//设置为在线状态update_state_online(db,username);}else{sprintf(src,"The user is online!");len=strlen(src);strcpy(dest,src);}}else{sprintf(src,"login fail : password error!");len=strlen(src);strcpy(dest,src);}}sqlite3_free_table(restr);return len;
}//查询单词,用链表存储查询到的单词信息,防止一词多义
linkList *select_word(sqlite3 *db,char *word,char *username)
{char buf[128]="";char *msg=NULL;char **restr=NULL;int row=0;int column=0;linkList *head=list_creat();sprintf(buf,"select annotation from wordsmsg where word=\"%s\"",word);if(sqlite3_get_table(db,buf,&restr,&row,&column,&msg)!=SQLITE_OK){ERR_MSG("get words fail",msg);return NULL;}if(row==0){list_insert_head(head,"Not found!"); }else{for(int i=row;i>0;i--){list_insert_head(head,restr[i]);}}//记录历史信息insert_history(db,word,username,head);sqlite3_free_table(restr);return head;
}//记录历史信息--数据库操作
int insert_history(sqlite3 *db,char *word,char *username,linkList *head)
{char buf[256]="";char tminfo[64]="";char *msg=NULL;time_t tocl=time(NULL);struct tm *info=localtime(&tocl);sprintf(tminfo,"%d-%02d-%02d %02d:%02d:%02d",\info->tm_year+1900,info->tm_mon+1,info->tm_mday,\info->tm_hour,info->tm_min,info->tm_sec);while(head->next!=NULL){head=head->next;sprintf(buf,"insert into %s values (\"%s\",\"%s\",\"%s\")",\username,word,head->msg,tminfo);if(sqlite3_exec(db,buf,NULL,NULL,&msg)!=SQLITE_OK){ERR_MSG("insert historymsg fail",msg);return -1;}}return 0;
}//查看历史查询信息,用链表存储查询到的历史信息
linkList *select_history(sqlite3 *db,char *username)
{char buf[128]="";char *msg=NULL;char **restr=NULL;int row=0;int column=0;linkList *head=list_creat();sprintf(buf,"select * from %s",username);if(sqlite3_get_table(db,buf,&restr,&row,&column,&msg)!=SQLITE_OK){ERR_MSG("get historymsg fail",msg);return NULL;}if(row==0){list_insert_head(head,"当前历史信息为空!"); }else{for(int i=row*column-1;i>=0;i--){list_insert_head(head,restr[i+3]);}}sqlite3_free_table(restr);return head;
}//处理接收到的客户端消息
int deal_rcvmsg(char *rcvmsg)
{int i=0;char *ch=rcvmsg+i;while(1){if(*ch=='#' && *(ch+1)=='#'){return i;}i++;ch=rcvmsg+i;}return 0;
}//处理客户端的注册请求
int do_register(int newfd,sqlite3 *db,char *rcvmsg)
{int index=0;int size=0;char sndmsg[256]="";char username[64]="";char password[64]="";index=deal_rcvmsg(rcvmsg);rcvmsg[index]='\0';strcpy(username,rcvmsg+1);strcpy(password,rcvmsg+index+2);size=user_register(db,username,password,sndmsg);mysendMsg(newfd,sndmsg,size);return 0;
}//修改用户状态为在线
int update_state_online(sqlite3 *db,char *username)
{char buf[128]="";char *msg=NULL;sprintf(buf,"update usermsg set state='online' where username=\"%s\"",username);if(sqlite3_exec(db,buf,NULL,NULL,&msg)!=SQLITE_OK){ERR_MSG("update state fail",msg);return -1;}return 0;
}//修改用户状态为离线
int update_state_offline(sqlite3 *db,char *username)
{char buf[128]="";char *msg=NULL;sprintf(buf,"update usermsg set state='offline' where username=\"%s\"",username);if(sqlite3_exec(db,buf,NULL,NULL,&msg)!=SQLITE_OK){ERR_MSG("update state fail",msg);return -1;}return 0;
}//处理客户端的登录请求
int do_login(int newfd,sqlite3 *db,char *rcvmsg)
{int size=0;int index=0;char sndmsg[256]="";char username[64]="";char password[64]="";index=deal_rcvmsg(rcvmsg);rcvmsg[index]='\0';strcpy(username,rcvmsg+1);strcpy(password,rcvmsg+index+2);size=user_login(db,username,password,sndmsg);mysendMsg(newfd,sndmsg,size);return 0;
}//处理客户端的查询单词请求
int do_select_world(int newfd,sqlite3 *db,char *username,char *rcvmsg)
{int size=0;char sndmsg[256]="";linkList *p;p=select_word(db,rcvmsg+1,username);while(p->next!=NULL){p=p->next;size=strlen(p->msg);mysendMsg(newfd,p->msg,size);}strcpy(sndmsg,"break");size=strlen(sndmsg);mysendMsg(newfd,sndmsg,size);list_destroy(p);p=NULL;return 0;
}//处理客户端的查看历史信息请求
int do_select_history(int newfd,sqlite3 *db,char *username)
{int size=0;char sndmsg[256]="";linkList *p;p=select_history(db,username);while(p->next!=NULL){p=p->next;size=strlen(p->msg);mysendMsg(newfd,p->msg,size);}strcpy(sndmsg,"break");size=strlen(sndmsg);mysendMsg(newfd,sndmsg,size);list_destroy(p);p=NULL;return 0;
}//以下功能代码,主要是为了减少TCP的粘包问题//发送指定大小数据
int writen(int fd,char *msg,int size)
{char *buf&#61;msg;int count&#61;size;int len&#61;0;while(count>0){len&#61;send(fd,buf,count,0);if(len<0){perror("send");return -1;}else if(0&#61;&#61;len){return size-count;}buf&#43;&#61;len;count-&#61;len;}return size;
}//发送数据
int mysendMsg(int fd,char *msg,int size)
{if(fd<0 || msg&#61;&#61;NULL || size<&#61;0){return -1;}char *buf&#61;(char *)malloc(size&#43;4);int len&#61;htonl(size);memcpy(buf,(char *)&len,4);memcpy(buf&#43;4,msg,size);int res&#61;writen(fd,buf,size&#43;4);if(res
int readn(int fd,char *msg,int size)
{char *buf&#61;msg;int count&#61;size;int len&#61;0;while(count>0){len&#61;recv(fd,buf,count,0);if(len<-1){perror("recv");return -1;}else if(0&#61;&#61;len){return 0;}buf&#43;&#61;len;count-&#61;len;}return size;
}//接受数据
int myrecvMsg(int fd,char **msg)
{int len;int res;res&#61;readn(fd,(char *)&len,4);if(res&#61;&#61;0){return 0;}len&#61;ntohl(len);char *buf&#61;(char *)malloc(len&#43;1);res&#61;readn(fd,buf,len);if(res
Ser.c&#xff1a;
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "SerOperation.h"typedef void (*sighandler_t)(int);//僵尸进程处理函数
void handler(int sig)
{while(waitpid(-1,NULL,WNOHANG)>0);
}int main(int argc, const char *argv[])
{if(argc<3){fprintf(stderr,"传参不足 %s ip port\n",argv[0]);return -1;}//创建流式套接字int sfd&#61;socket(AF_INET,SOCK_STREAM,0);if(sfd<0){perror("socket fail");return -1;}//允许端口快速重用int reuse&#61;1;if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))<0){perror("setsockopt");return -1;}//填充服务器地址信息结构体struct sockaddr_in sin;sin.sin_family&#61;AF_INET;sin.sin_port&#61;htons(atoi(argv[2]));sin.sin_addr.s_addr&#61;inet_addr(argv[1]);//绑定ip和端口if(bind(sfd,(struct sockaddr *)&sin,sizeof(sin))<0){perror("bind fail");return -1;}//设置为被动监听状态if(listen(sfd,10)<0){perror("listen fail");return -1;}//信号处理僵尸进程if(signal(SIGCHLD,handler)&#61;&#61;SIG_ERR){perror("signal fail");return -1;}//储存客户端地址信息结构体struct sockaddr_in cin;socklen_t addrlen;//创建数据库,并将单词导入数据库//drop_table();sqlite3 *db&#61;create_database();//import_words(db);int newfd;char username[64]&#61;""; //用来保存登录的用户名char *rcvmsg&#61;NULL;//循环等待客户端连接while(1){newfd&#61;accept(sfd,(struct sockaddr *)&cin,&addrlen);if(newfd<0){perror("accept fail");return -1;}printf("[ %s : %d ]connect\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port));//如果有客户端连接就去创建一个子进程与客户端通信//父进程继续等待其他客户端连接pid_t pid&#61;fork();if(pid>0){close(newfd);}else if(0&#61;&#61;pid){close(sfd);while(1){rcvmsg&#61;NULL;if(0&#61;&#61;myrecvMsg(newfd,&rcvmsg)){//用户掉线&#xff0c;用户状态设置为离线状态update_state_offline(db,username);printf("[ %s : %d ]quit\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port));break;}switch(rcvmsg[0]){case &#39;R&#39;:do_register(newfd,db,rcvmsg);free(rcvmsg);break;case &#39;L&#39;:bzero(username,sizeof(username));do_login(newfd,db,rcvmsg);strcpy(username,rcvmsg&#43;1);free(rcvmsg);break;case &#39;F&#39;:do_select_world(newfd,db,username,rcvmsg);free(rcvmsg);break;case &#39;H&#39;:do_select_history(newfd,db,username);free(rcvmsg);break;case &#39;Q&#39;:update_state_offline(db,username);free(rcvmsg);break;default:continue;}}close(newfd);exit(0);}else{perror("fork fail");return -1;}}//关闭套接字close(sfd);//关闭数据库close_database(db);db&#61;NULL;return 0;
}
客户端&#xff1a;
所需头文件&#xff1a;CliOperation.h
所需源文件&#xff1a;CliOperation.c
主函数源文件&#xff1a;Cli.c
CliOperation.h&#xff1a;
#ifndef __CLIOPERATION_H__
#define __CLIOPERATION_H__#include
#include
#include
#include
#include
#include
void pri_menu();//功能菜单
void fun_menu(int cfd);int Register(int cfd);int Login(int cfd);int Quit(int cfd);int SelectWord(int cfd);int SelectHistory(int cfd);int writen(int fd,char *msg,int size);
int mysendMsg(int fd,char *msg,int size);
int readn(int fd,char *msg,int size);
int myrecvMsg(int fd,char **msg);#endif
CliOperation.c&#xff1a;
#include "./CliOperation.h"void pri_menu()
{printf("\t************************\n");printf("\t*******电 子 词 典******\n");printf("\t********1> 注 册********\n");printf("\t********2> 登 录********\n");printf("\t********3> 退 出********\n");printf("\t************************\n");
}void fun_menu(int cfd)
{char choose;while(1){system("clear");printf("\t***************************\n");printf("\t********用 户 功 能********\n");printf("\t********1> 查询单词********\n");printf("\t********2> 查看历史记录****\n");printf("\t********3> 放回上一级******\n");printf("\t***************************\n");fprintf(stdout,"请输入你的选择>>>");choose&#61;getchar();while(getchar()!&#61;&#39;\n&#39;);switch(choose){case &#39;1&#39;:SelectWord(cfd);break;case &#39;2&#39;:SelectHistory(cfd);break;case &#39;3&#39;:Quit(cfd);return ;default:fprintf(stderr,"input choose error,try again\n");break;}fprintf(stdout,"请输入任意字符清屏>>>");fflush(stdout);while(getchar()!&#61;&#39;\n&#39;);}
}//用户注册
int Register(int cfd)
{char sndmsg[256]&#61;"";char *rcvmsg&#61;NULL;char username[64]&#61;"";char password[64]&#61;"";int size&#61;0;//输入用户名fprintf(stdout,"请输入用户名>>>");fgets(username,sizeof(username),stdin);username[strlen(username)-1]&#61;0;size&#43;&#61;strlen(username);//输入密码fprintf(stdout,"请输入密码>>>");fgets(password,sizeof(password),stdin);password[strlen(password)-1]&#61;0;size&#43;&#61;strlen(password);//发送用户名和密码给服务器sndmsg[0]&#61;&#39;R&#39;;sprintf(sndmsg&#43;1,"%s##%s",username,password);mysendMsg(cfd,sndmsg,size&#43;3);//接收结果信息myrecvMsg(cfd,&rcvmsg);//处理信息fprintf(stdout,"%s\n",rcvmsg);free(rcvmsg);return 0;
}//用户登录
int Login(int cfd)
{char sndmsg[256]&#61;"";char *rcvmsg&#61;NULL;;char username[64]&#61;"";char password[64]&#61;"";int size&#61;0;//输入用户名fprintf(stdout,"请输入用户名>>>");fgets(username,sizeof(username),stdin);username[strlen(username)-1]&#61;0;size&#43;&#61;strlen(username);//输入密码fprintf(stdout,"请输入密码>>>");fgets(password,sizeof(password),stdin);password[strlen(password)-1]&#61;0;size&#43;&#61;strlen(password);//发送用户名和密码给服务器sndmsg[0]&#61;&#39;L&#39;;sprintf(sndmsg&#43;1,"%s##%s",username,password);mysendMsg(cfd,sndmsg,size&#43;3);//接收结果信息myrecvMsg(cfd,&rcvmsg);//处理信息fprintf(stdout,"%s\n",rcvmsg);if(strcmp(rcvmsg,"login success!")&#61;&#61;0){return 1;}free(rcvmsg);return 0;
}//用户退出
int Quit(int cfd)
{char sndmsg&#61;&#39;Q&#39;;mysendMsg(cfd,&sndmsg,1);return 0;
}//查询单词
int SelectWord(int cfd)
{char sndmsg[256];char *rcvmsg&#61;NULL;int size&#61;0;//输入要查询的单词sndmsg[0]&#61;&#39;F&#39;;fprintf(stdout,"请输入你要查询的单词>>>");fgets(sndmsg&#43;1,sizeof(sndmsg),stdin);sndmsg[strlen(sndmsg)-1]&#61;0;size&#61;strlen(sndmsg);//发送单词给服务器mysendMsg(cfd,sndmsg,size&#43;1);//接收结果信息while(1){myrecvMsg(cfd,&rcvmsg);//处理信息if(strcmp(rcvmsg,"break")&#61;&#61;0){free(rcvmsg);break;}fprintf(stdout,"%s\n",rcvmsg);free(rcvmsg);}return 0;
}//查看历史记录
int SelectHistory(int cfd)
{char sndmsg&#61;&#39;H&#39;;char *rcvmsg&#61;NULL;int i&#61;0;//给服务器发送请求mysendMsg(cfd,&sndmsg,1);//接收结果信息while(1){myrecvMsg(cfd,&rcvmsg);//处理信息if(strcmp(rcvmsg,"break")&#61;&#61;0){free(rcvmsg);break;}fprintf(stdout,"%s",rcvmsg);i&#43;&#43;;if(i%3&#61;&#61;0){putchar(10);}else{printf("\t\t");}free(rcvmsg);}if(1&#61;&#61;i){putchar(10);}return 0;
}//以下功能代码&#xff0c;主要是为了减少TCP的粘包问题//发送指定大小数据
int writen(int fd,char *msg,int size)
{char *buf&#61;msg;int count&#61;size;while(count>0){int len&#61;send(fd,buf,count,0);if(len<0){perror("send");return -1;}else if(0&#61;&#61;len){return size-count;}buf&#43;&#61;len;count-&#61;len;}return size;
}//发送数据
int mysendMsg(int fd,char *msg,int size)
{if(fd<0 || msg&#61;&#61;NULL || size<&#61;0){return -1;}char *buf&#61;(char *)malloc(size&#43;4);int len&#61;htonl(size);memcpy(buf,(char *)&len,4);memcpy(buf&#43;4,msg,size);int res&#61;writen(fd,buf,size&#43;4);if(res
int readn(int fd,char *msg,int size)
{char *buf&#61;msg;int count&#61;size;int len&#61;0;while(count>0){int len&#61;recv(fd,buf,count,0);if(len<-1){perror("recv");return -1;}else if(0&#61;&#61;len){return 0;}buf&#43;&#61;len;count-&#61;len;}return size;
}//接受数据
int myrecvMsg(int fd,char **msg)
{int len;int res;res&#61;readn(fd,(char *)&len,4);if(res&#61;&#61;0){return 0;}len&#61;ntohl(len);char *buf&#61;(char *)malloc(len&#43;1);res&#61;readn(fd,buf,len);if(res
Cli.c&#xff1a;
#include
#include
#include
#include
#include
#include
#include "./CliOperation.h"int main(int argc, const char *argv[])
{if(argc<3){fprintf(stderr,"传参不足 %s ip port\n",argv[0]);return -1;}//创建流式套接字int cfd&#61;socket(AF_INET,SOCK_STREAM,0);if(cfd<0){perror("socket");return -1;}//非绑定//填充服务器地址信息结构体struct sockaddr_in sin;sin.sin_family&#61;AF_INET;sin.sin_port&#61;htons(atoi(argv[2]));sin.sin_addr.s_addr&#61;inet_addr(argv[1]);//连接服务器if(connect(cfd,(struct sockaddr *)&sin,sizeof(sin))<0){perror("connect");return -1;}char msg[256];char choose;while(1){
START:system("clear");pri_menu();fprintf(stdout,"请输入你的选择>>>");choose&#61;getchar();while(getchar()!&#61;&#39;\n&#39;);switch(choose){case &#39;1&#39;:Register(cfd); break;case &#39;2&#39;:if(Login(cfd)&#61;&#61;1){fun_menu(cfd);goto START;}break;case &#39;3&#39;:goto END;break;default:fprintf(stderr,"input choose error,try again!\n");break;}fprintf(stdout,"请输入任意字符清屏>>>");fflush(stdout);while(getchar()!&#61;&#39;\n&#39;);}END:close(cfd);return 0;
}
Makefile&#xff1a;
TARGET:&#61;main
SER:&#61;ser
CLI:&#61;cli
CAN:&#61;-c -o
CC:&#61;gcc
OBJS:&#61;Ser.o SerOperation.o linklist.o
OBJC:&#61;Cli.o CliOperation.o$(TARGET):$(OBJS) $(OBJC)$(CC) $(OBJS) -o $(SER) -lsqlite3$(CC) $(OBJC) -o $(CLI) %.o:%.c$(CC) $<$(CAN) $&#64;clean:rm -rf $(OBJS) $(OBJC) $(SER) $(CLI)
运行效果&#xff1a;
注册&#xff1a;
登录&#xff1a;
查询单词&#xff1a;
查看历史记录&#xff1a;
退出&#xff1a;
查看图形化数据库&#xff1a;