热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

项目:电子词典

项目要求服务器:所需头文件:linklist.hSerOperation.h所需源文件:linklist.cSerOperation.c主

项目要求

 服务器:

        所需头文件:linklist.h   SerOperation.h

        所需源文件:linklist.c   SerOperation.c

        主函数源文件:Ser.c

        linklist.h:

#ifndef __LINKLIST_H__
#define __LINKLIST_H__#include
#include
#include #define N 128typedef struct Node{char msg[N];struct Node *next;
}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 #define ERR_MSG(msg1,msg2) do{\fprintf(stderr,"__%s__ __%d__\n",__func__,__LINE__);\fprintf(stderr,"%s : %s\n",msg1,msg2);\
}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;


推荐阅读
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • 基于PgpoolII的PostgreSQL集群安装与配置教程
    本文介绍了基于PgpoolII的PostgreSQL集群的安装与配置教程。Pgpool-II是一个位于PostgreSQL服务器和PostgreSQL数据库客户端之间的中间件,提供了连接池、复制、负载均衡、缓存、看门狗、限制链接等功能,可以用于搭建高可用的PostgreSQL集群。文章详细介绍了通过yum安装Pgpool-II的步骤,并提供了相关的官方参考地址。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 本文介绍了在rhel5.5操作系统下搭建网关+LAMP+postfix+dhcp的步骤和配置方法。通过配置dhcp自动分配ip、实现外网访问公司网站、内网收发邮件、内网上网以及SNAT转换等功能。详细介绍了安装dhcp和配置相关文件的步骤,并提供了相关的命令和配置示例。 ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • javascript  – 概述在Firefox上无法正常工作
    我试图提出一些自定义大纲,以达到一些Web可访问性建议.但我不能用Firefox制作.这就是它在Chrome上的外观:而那个图标实际上是一个锚点.在Firefox上,它只概述了整个 ... [详细]
  • 本文介绍了Oracle数据库中tnsnames.ora文件的作用和配置方法。tnsnames.ora文件在数据库启动过程中会被读取,用于解析LOCAL_LISTENER,并且与侦听无关。文章还提供了配置LOCAL_LISTENER和1522端口的示例,并展示了listener.ora文件的内容。 ... [详细]
  • 本文介绍了计算机网络的定义和通信流程,包括客户端编译文件、二进制转换、三层路由设备等。同时,还介绍了计算机网络中常用的关键词,如MAC地址和IP地址。 ... [详细]
  • Nginx使用AWStats日志分析的步骤及注意事项
    本文介绍了在Centos7操作系统上使用Nginx和AWStats进行日志分析的步骤和注意事项。通过AWStats可以统计网站的访问量、IP地址、操作系统、浏览器等信息,并提供精确到每月、每日、每小时的数据。在部署AWStats之前需要确认服务器上已经安装了Perl环境,并进行DNS解析。 ... [详细]
  • vue使用
    关键词: ... [详细]
author-avatar
qweqwe
这个家伙不难、有留下一点东西、留下了脚印~!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有