实现逻辑
逻辑图
源代码:
1:服务器(分文件编程,主函数文件,功能函数文件,头文件)
1,主函数
#include "head1.h"
int main(int argc, const char *argv[])
{
//创建流式套接字
int sfd=socket(AF_INET,SOCK_STREAM,0);
if(sfd<0)
{
ERR_MSG("socket");
return -1;
}
printf("create socket success\n");
//允许端口快速复用
int reuse=1;
if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))<0)
{
ERR_MSG("setsockopt");
return -1;
}
//填充地址信息结构体,真是的地址信息结构体与协议族相关
//AF_INET,所以详情请看man 7ip
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT); //网络字节序端口号
sin.sin_addr.s_addr = inet_addr(IP) ; //网络字节序的IP地址
//将地址信息结构体绑定到套接字上
if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))<0)
{
ERR_MSG("bind");
return -1;
}
printf("bind success\n");
//将套接字设置为被动监听状态
if(listen(sfd,128)<0)
{
ERR_MSG("listen");
return -1;
}
printf("listen success\n");
//打开数据库
sqlite3 *db=seq_open();
//创建链表
USER *H=create_list(sfd);
if(NULL==H) return -1;
while(1)
{
struct sockaddr_in cin;
socklen_t addrlen = sizeof(cin);
//从已完成连接的队列头中,取出一个客户端的信息,创建生成一个新的套接字文件描述符
//该文件描述符才是与客户端通信的文件描述符
int newfd = accept(sfd,(struct sockaddr*)&cin,&addrlen);
if(newfd < 0)
{
ERR_MSG("accept");
return -1;
}
if(insert_list(H,newfd,cin,db)==0)
{
//创建新的客户线程,处理客户端信息,与客户进行交互
pthread_t tid2;
if(pthread_create(&tid2,NULL,deal_climsg,(void*)H)<0)
{
ERR_MSG("pthread_create");
return -1;
}
}
}
close(sfd);
return 0;
}
2,功能函数
#include "head1.h"
//创建链表
USER * create_list(int sfd)
{
//创建链表
USER *H=(USER*)malloc(sizeof(USER));
if(NULL==H)
{
puts("链表创建失败");
return NULL;
}
//初始化链表
H->next=NULL;
H->size=0;
H->newfd=sfd;
return H;
}
//尾插连入客户链表
int insert_list(USER *H,int newfd,struct sockaddr_in cin,sqlite3 *db)
{
//判断是不是新的客户
USER *p=H;
while(p->next!=NULL)
{
if(newfd==p->newfd)
{
break;
return -1;
}
p=p->next;
}
if(NULL==p->next)
{
//初始化新增节点
USER *new=(USER*)malloc(sizeof(USER));
new->newfd=newfd;
new->cin=cin;
new->db=db;
new->next=NULL;
//尾插连入链表
p->next=new;
//表的变化
H->size++;
}
return 0;
}
//发送信息
int send_msg(int newfd,char *buf,int size)
{
ssize_t res;
if((res=send(newfd,buf,size,0))<0)
{
ERR_MSG("send");
return -1;
}
return 0;
}
//删除指定节点
int delet_point(USER *H,int sfd)
{
USER *p=H;
while(p->next!=NULL)
{
if(p->next->newfd == sfd)
{
USER *q=p->next;
p->next=q->next;
free(q);
q=NULL;
break;
}
p=p->next;
}
return 0;
}
//判断登录信息
int log_in(USER *H,int newfd,char *buf)
{
char msg[128]="";
USER*p=H->next;
while(p!=NULL)
{
if(p->newfd==newfd)
{
break;
}
p=p->next;
}
sqlite3 *db=p->db;
sprintf(msg,"select cli_msg from cli where cli_msg=\"%s\"",buf);
printf("__%d__%s\n",__LINE__,msg);
int row=0,column=0;
if(search_seq(db,msg,&row,&column)!=NULL)
{
return 0;
}
return -1;
}
//判断注册信息
int regis(USER *H,int newfd,char *buf)
{
char msg[128]="";
USER*p=H->next;
while(p!=NULL)
{
if(p->newfd==newfd)
{
break;
}
p=p->next;
}
sqlite3 *db=p->db;
sprintf(msg,"select cli_msg from cli where cli_msg=\"%s\";",buf);
printf("__%d__%s\n",__LINE__,msg);
int row=0,column=0;
if(search_seq(db,msg,&row,&column)!=NULL)
{
return -1;
}
bzero(msg,sizeof(msg));
sprintf(msg,"insert into cli values (\"%s\");",buf);
printf("__%d__%s\n",__LINE__,msg);
if(insert_seq(db,msg)<0)
{
return -1;
}
return 0;
}
//查找单词
int search_word(USER *H,int newfd,char *buf,char *user_msg,char *msg)
{
char msg1[128]="";
USER*p=H->next;
while(p!=NULL)
{
if(p->newfd==newfd)
{
break;
}
p=p->next;
}
sqlite3 *db=p->db;
sprintf(msg1,"select mean from dict where word=\"%s\";",buf);
//printf("%s\n",msg);
int row,column;
char **pres=NULL;
pres=search_seq(db,msg1,&row,&column);
if(NULL==pres)
{
return -1;
}
char *find_word=pres[1];
printf("%s\n",find_word);
if(find_word != NULL)
{
bzero(msg1,sizeof(msg1));
time_t t;
time(&t);
char *str=ctime(&t);
sprintf(msg1,"insert into history values (\"%s\",\"%s\",\"%s\",\"%s\")"\
,user_msg,buf,find_word,str);
printf("%s\n",msg1);
insert_seq(db,msg1);
strcpy(msg,find_word);
return 0;
}
return -1;
}
//发送历史查询数据
int history_send(USER*H,int newfd,char *buf)
{
char msg[128]="";
USER*p=H->next;
while(p!=NULL)
{
if(p->newfd==newfd)
{
break;
}
p=p->next;
}
sqlite3 *db=p->db;
sprintf(msg,"select word,mean,time from history where cli_msg=\"%s\";",buf);
int row,column;
char **pres=NULL;
pres=search_seq(db,msg,&row,&column);
if(NULL==pres)
{
strcpy(msg,"over");
send_msg(newfd,msg,strlen(msg)+1);
return -1;
}
bzero(msg,sizeof(msg));
for(int i=0;i<(column*(row+1));i+=3)
{
sprintf(msg,"%s\t\t%s\t\t\t%s\n",pres[i],pres[i+1],pres[i+2]);
send_msg(newfd,msg,strlen(msg));
}
sleep(1);
bzero(msg,sizeof(msg));
strcpy(msg,"over");
send_msg(newfd,msg,strlen(msg));
}
//处理客户端信息线程
void *deal_climsg(void *arg)
{
pthread_detach(pthread_self());
USER *H=(USER*)arg;
USER *p=H;
while(p->next!=NULL)
{
p=p->next;
}
int newfd =p->newfd;
char buf[128]="";
ssize_t res=0;
char user_msg[128]="";
while(1)
{
//接收客户端发来的登录交互信息
bzero(buf,sizeof(buf));
res=recv(newfd,buf,sizeof(buf),0);
if(res<0)
{
ERR_MSG("recv");
return NULL;
}
else if(0==res)
{
printf("[%s : %d] newfd =%d客户端退出\n",inet_ntoa((p->cin).sin_addr),ntohs((p->cin).sin_port),newfd);
delet_point(H,newfd);
break;
}
int *num=(int*)buf;
if(1 == *num)
{
char msg[128]="";
printf("进入登录界面\n");
//printf("%s\n",buf+4);
//判断登录信息
if(log_in(H,newfd,buf+4)<0)
{
strcpy(msg,"fail");
send_msg(newfd,msg,strlen(msg));
}else{
strcpy(user_msg,buf+4);
strcpy(msg,"success");
send_msg(newfd,msg,strlen(msg));
}
}else if(2 ==*num)
{
char msg[128]="";
printf("进入注册界面\n");
//printf("%s\n",buf+4);
//判断注册
if(regis(H,newfd,buf+4)<0)
{
strcpy(msg,"fail");
send_msg(newfd,msg,strlen(msg));
}else{
strcpy(msg,"success");
send_msg(newfd,msg,strlen(msg));
}
}else if(3==*num)
{
char msg[128]="";
printf("进入查单词界面\n");
//printf("%s\n",buf+4);
//判断查询
int p=0;
p=search_word(H,newfd,buf+4,user_msg,msg);
printf("%s\n",msg);
if(p<0)
{
strcpy(msg,"fail");
send_msg(newfd,msg,strlen(msg));
}else{
send_msg(newfd,msg,strlen(msg));
}
}else if(4==*num)
{
history_send(H,newfd,buf+4);
}else if(5==*num)
{
delet_point(H,newfd);
printf("已退出\n");
pthread_exit(0);
}
}
}
//打开数据库
sqlite3 * seq_open()
{
sqlite3 *db=NULL;
if(sqlite3_open("./my.db",&db) != SQLITE_OK)
{
printf("errno=%d\n",sqlite3_errcode(db));
printf("err_msg=%s\n",sqlite3_errmsg(db));
printf("__%d__ seqlite open fail\n",__LINE__);
return NULL;
}
printf("sqlite3_open success\n");
return db;
}
//插入数据
int insert_seq(sqlite3 *db,char *msg)
{
char sql[128] = "";
strcpy(sql,msg);
char * errmsg=NULL;
if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!= SQLITE_OK)
{
printf("__%d__ sqlite3__exec %s\n",__LINE__,errmsg);
return -1;
}
printf("insert success\n");
return 0;
}
//删除数据
int delete_seq(sqlite3 *db)
{
printf("请输入要删除的成员id\n");
int temp;
scanf("%d",&temp);
while(getchar()!=10);
char sql[128] = "";
sprintf(sql,"delete from stu where id =%d;",temp);
char * errmsg=NULL;
if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!= SQLITE_OK)
{
printf("__%d__ sqlite3__exec %s\n",__LINE__,errmsg);
}
}
//修改数据
int change_seq(sqlite3 *db)
{
int id;
float score;
printf("请输入要修改的成员id:");
scanf("%d",&id);
while(getchar()!=10);
printf("请输入修改后的成绩:");
scanf("%f",&score);
while(getchar()!=10);
char sql[128] = "";
sprintf(sql,"update stu set score=%f where id=%d;",score,id);
char * errmsg=NULL;
if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!= SQLITE_OK)
{
printf("__%d__ sqlite3__exec %s\n",__LINE__,errmsg);
}
}
//查询数据库信息
char** search_seq(sqlite3 *db,char *buf,int* row,int* column)
{
char sql[128] = "";
strcpy(sql,buf);
char ** pres =NULL; //储存查询到的字符串数组
char * errmsg=NULL; //错误信息
printf("__%d__%s\n",__LINE__,sql);
if(sqlite3_get_table(db,sql,&pres,row,column,&errmsg) != SQLITE_OK)
{
fprintf(stderr,"__%d__ sqlite3__exec %s\n",__LINE__,errmsg);
return NULL;
}
if(0 == *row)
{
return NULL;
}
return pres;
}
头文件
#ifndef __HEAD_H__
#define __HEAD_H__
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <dirent.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sqlite3.h>
#include <time.h>
//打印错误信息宏函数
#define ERR_MSG(msg) do{\
fprintf(stderr,"__%d__",__LINE__);\
perror(msg);\
}while(0)
//用户信息结构体
typedef struct node{
struct sockaddr_in cin;
int newfd;
union{
sqlite3 *db;
int size;
};
struct node *next;
}USER;
#define PORT 8888 //1024~49151
#define IP "192.168.31.73" //本机IP ifconfig查看
//用户管理函数
//创建链表
USER* create_list(int sfd);
//尾插连入客户链表
int insert_list(USER *H,int newfd,struct sockaddr_in cin,sqlite3 *db);
//服务器发送线程
void* wri_send(void*arg);
//发送信息
int send_msg(int newfd,char *buf,int size);
//删除指定节点
int delet_point(USER *H,int sfd);
//处理客户端信息线程
void *deal_climsg(void *arg);
//处理信息包函数
//判断登录信息
int log_in(USER *H,int newfd,char *buf);
//判断注册信息
int regis(USER *H,int newfd,char *buf);
//查找单词
int search_word(USER *H,int newfd,char *buf,char *user_msg,char *msg);
//发送历史查询数据
int history_send(USER*H,int newfd,char *buf);
//数据库管理函数
//打开数据库
sqlite3 * seq_open();
//插入数据
int insert_seq(sqlite3 *db,char *msg);
//删除数据
int delete_seq(sqlite3 *db);
//修改数据
int change_seq(sqlite3 *db);
//查询数据
char **search_seq(sqlite3 *db,char *buf,int* cow,int* column);
#endif
用户端 分文件编程:主函数文件,功能函数文件,头文件
主函数
#include "2_head.h"
int main(int argc, const char *argv[])
{
//捕获17号信号
sighandler_t s=signal(SIGINT,handler);
if(SIG_ERR==s)
{
perror("signal");
return -1;
}
//创建流式套接字
sfd=socket(AF_INET,SOCK_STREAM,0);
if(sfd<0)
{
ERR_MSG("socket");
return -1;
}
printf("create socket success\n");
//允许端口快速复用
int reuse=1;
if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))<0)
{
ERR_MSG("setsockopt");
return -1;
}
printf("setsockopt success\n");
//绑定客户端信息结构体
//填充要连接的服务器的地址信息结构体‘
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.s_addr = inet_addr(IP);
//连接服务器
if(connect(sfd,(struct sockaddr*)&sin,sizeof(sin))<0)
{
ERR_MSG("connect");
return -1;
}
//创建要发送的包
char buf[128]="";
//接收服务器信息的包
char rcv[128]="";
ssize_t res =0;
//客户端处理流程
while(1)
{
system("clear");
home_page();
int num;
scanf("%d",&num);
while(getchar()!=10);
switch(num)
{
case 1: //登录
{
int size;
char user[128]="";
while(1)
{
system("clear");
size=log_in(buf);
if(size <0)
{
break;
}
if(send_msg(sfd,buf,size)<0)
{
return -1;
}
//接收
bzero(rcv,sizeof(rcv));
res=recv(sfd,rcv,sizeof(rcv),0);
if(res<0)
{
ERR_MSG("recv");
return -1;
}else if(res==0)
{
printf("服务器关闭\n");
return -1;
}
if(strcmp(rcv,"success")==0)
{
break;
}
printf("输入错误,请重试\n");
printf("按任意键,清屏\n");
while(getchar()!=10);
}
if(size<0)
{
break;
}
strcpy(user,buf+4);
work(sfd,user);
}
break;
case 2: //注册
{
while(1)
{
system("clear");
bzero(buf,sizeof(buf));
//system("clear");
int size=regis(buf);
if(send_msg(sfd,buf,size)<0)
{
return -1;
}
//接收
bzero(rcv,sizeof(rcv));
res=recv(sfd,rcv,sizeof(rcv),0);
if(res<0)
{
ERR_MSG("recv");
return -1;
}else if(res==0)
{
printf("服务器关闭\n");
return -1;
}
if(strcmp(rcv,"success")==0)
{
break;
}else
{
printf("该用户已注册,请直接登录\n");
printf("请按任意键返回\n");
while(getchar()!=10);
break;
}
}
}
break;
case 3:
{
//退出词典
log_out(sfd);
exit(0);
}
break;
default:printf("输入错误,请重新输入\n");
}
}
close(sfd);
return 0;
}
功能函数
#include "2_head.h"
//发送信息线程
void* wri_send(void*arg)
{
pthread_detach(pthread_self());
char buf[128]="";
ssize_t res;
int sfd=*((int*)arg);
while(1)
{
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1]=0;
res=send(sfd,buf,sizeof(buf),0);
if(res<0)
{
ERR_MSG("send");
return NULL;
}
}
}
//发送信息
int send_msg(int sfd,char *buf,int size)
{
ssize_t res;
if((res=send(sfd,buf,size,0))<0)
{
ERR_MSG("send");
return -1;
}
return 0;
}
//词典首页
void home_page()
{
printf("*****无道词典******\n");
printf("** 1,登录 **\n");
printf("** 2,注册 **\n");
printf("** 3,退出 **\n");
printf("*******************\n");
printf("请输入>>>");
}
//登录界面
int log_in(char *buf)
{
//封装登录包
char *p=buf;
int *q=(int*)p;
*q=1;
p=p+4;
//定义用户信息数组:用户名&密码
char temp[128]="";
//
printf("******欢迎登录******\n");
printf("提示:按0退出该界面 \n");
printf("请输入用户名>>>");
fgets(temp,sizeof(temp),stdin);
temp[strlen(temp)-1]=0;
if(strcmp(temp,"0")==0)
{
return -1;
}
//将用户名拷贝进包
strcpy(p,temp);
*(p+strlen(temp))='&';
*(p+strlen(temp)+1)=0;
//输入密码
bzero(temp,sizeof(temp));
printf("请输入密码>>>");
fgets(temp,sizeof(temp),stdin);
temp[strlen(temp)-1]=0;
strcat(p,temp);
int size=4+strlen(p)+1;
return size;
}
//注册界面
int regis(char *buf)
{
//封装注册包
char *p=buf;
int *q=(int*)p;
*q=2;
p=p+4;
//定义用户信息数组:用户名&密码
char temp[128]="";
//
printf("******欢迎注册******\n");
printf("请输入用户名>>>");
fgets(temp,sizeof(temp),stdin);
temp[strlen(temp)-1]=0;
//将用户名拷贝进包
strcpy(p,temp);
*(p+strlen(temp))='&';
*(p+strlen(temp)+1)=0;
//输入密码
bzero(temp,sizeof(temp));
printf("请输入密码>>>");
fgets(temp,sizeof(temp),stdin);
temp[strlen(temp)-1]=0;
strcat(p,temp);
int size=4+strlen(p)+1;
return size;
}
//工作界面
void work_menu()
{
printf("*****欢迎使用无道词典******\n");
printf("** 1,查询单词 **\n");
printf("** 2,查询历史 **\n");
printf("** 3,退出登录 **\n");
printf("***************************\n");
printf("请输入>>>");
}
//封装单词查询包
int word(char *buf)
{
//封装单词查询包
char *p=buf;
int *q=(int*)p;
*q=3;
p=p+4;
//定义用户信息数组:用户名&密码
char temp[128]="";
//
printf("******单词查询服务******\n");
printf("*********按0退出********\n");
printf("请输入单词>>>");
fgets(temp,sizeof(temp),stdin);
temp[strlen(temp)-1]=0;
if(strcmp(temp,"0")==0)
{
return -1;
}
strcpy(p,temp);
int size=4+strlen(temp)+1;
return size;
}
//查看历史信息
int search_history(int sfd,char *user)
{
char buf[128]="";
char rcv[128]="";
//封装单词查询包
char *p=buf;
int *q=(int*)p;
*q=4;
p=p+4;
printf("******历史查询服务******\n");
printf("******按任意键退出******\n");
strcpy(p,user);
send_msg(sfd,buf,strlen(p)+4);
ssize_t res=0;
while(1)
{
bzero(rcv,sizeof(rcv));
res=recv(sfd,rcv,sizeof(rcv),0);
if(res<0)
{
ERR_MSG("recv");
return -1;
}else if(res==0)
{
printf("服务器关闭\n");
return -1;
}
if(strcmp(rcv,"over")==0)
{
break;
}
printf("%s",rcv);
}
while(getchar()!=10);
}
//查单词,查历史
int work(int sfd,char *user)
{
int num;
//定义交互包
char buf[128]="";
char rcv[128]="";
ssize_t res=0;
while(1)
{
system("clear");
work_menu();
scanf("%d",&num);
while(getchar()!=10);
switch(num)
{
case 1:
{
int size=0;
while(1)
{
system("clear");
size=word(buf);
if(size<0)
{
break;
}
send_msg(sfd,buf,size);
//接收
bzero(rcv,sizeof(rcv));
res=recv(sfd,rcv,sizeof(rcv),0);
if(res<0)
{
ERR_MSG("recv");
return -1;
}else if(res==0)
{
printf("服务器关闭\n");
return -1;
}
if(strcmp(rcv,"fail")==0)
{
printf("未查询到\n");
}else{
printf("%s\n",rcv);
}
printf("按任意键清屏\n");
while(getchar()!=10);
}
}
break;
case 2:
{
system("clear");
//查看历史信息并打印
search_history(sfd,user);
}
break;
case 3:
{
//自己退出
return 0;
}
break;
default:printf("输入错误,请重新输入\n");
}
}
}
//退出登录
int log_out(int sfd)
{
char buf[128]="";
//封装退出包
char *p=buf;
int *q=(int*)p;
*q=5;
send_msg(sfd,buf,4);
}
void handler(int sig)
{
log_out(sfd);
exit(0);
return;
}
头文件
#ifndef __HEAD_H__
#define __HEAD_H__
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <dirent.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
//打印错误信息宏函数
#define ERR_MSG(msg) do{\
fprintf(stderr,"__%d__",__LINE__);\
perror(msg);\
}while(0)
//服务器IP和端口号
#define PORT 8888 //1024~49151
#define IP "192.168.31.73" //本机IP ifconfig查看
int sfd;
//词典首页
void home_page();
//发送信息
int send_msg(int sfd,char *buf,int size);
//发送信息线程
void* wri_send(void*arg);
//登录界面
int log_in(char *buf);
//注册界面
int regis(char *buf);
//工作界面
int work(int sfd,char *user);
//查看历史信息
int search_history(int sfd,char *user);
//退出登录
int log_out(int sfd);
typedef void (*sighandler_t)(int);
void handler(int sig);
#endif