android开发实战 matlab 分库查询 ISP linq solr 后台ui模板 seo教程下载 erp系统源码 jquery的each遍历方法 java多行注释 docker查看所有容器 pcm接口 docker启动命令 python3教程 python搭建环境 python类和对象 java斐波那契数列 java语言基础教程 java的继承 java中的对象 java使用正则表达式 java接口类型 java中泛型 java替换字符串 java中continue java语言编程 java数据类型转换 decimalformat m4a转mp3格式转换器 手机照片恢复免费软件 华为交换机学习指南 kontakt 骰子动态图 备份数据的软件 快手规则 战法装备 键盘灯怎么关 谷歌地球怎么用不了 ajax获取数据
当前位置: 首页 > 学习教程  > 编程语言

在线词典(服务器,客服端,Makefile)

2020/9/19 16:16:11 文章标签: 测试文章如有侵权请发送至邮箱809451989@qq.com投诉后文章立即删除

server:
/*================================================================
*

  • 文件名称:在线词典服务器v1.0.c
  • 创 建 者:xiaowang
  • 创建日期:2020年04月28日
  • 描 述:

================================================================*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <sqlite3.h>
#include <signal.h>
#include <time.h>
#include <sys/wait.h>
#include <unistd.h>

#define N 32

#define R 1 // user - register
#define L 2 // user - login
#define Q 3 // user - query
#define H 4 // user - history

#define DATABASE “my.db”

// 定义通信双方的信息结构体
typedef struct {
int type;
char name[N];
char data[256];
}attribute((packed)) MSG;

int do_client(int acceptfd, sqlite3 *db);
void do_register(int acceptfd, MSG *msg, sqlite3 *db);
int do_login(int acceptfd, MSG *msg, sqlite3 db);
int do_query(int acceptfd, MSG msg, sqlite3 db);
int do_history(int acceptfd, MSG msg, sqlite3 db);
int history_callback(void
arg,int f_num,char
f_value,char
f_name);
int do_searchword(int acceptfd, MSG *msg, char word[]);
int get_date(char *date);

void sig_child_handle(int signo)
{
if(SIGCHLD == signo)
waitpid(-1, NULL, WNOHANG);
}

//0主函数
int main(int argc, const char *argv[])
{

int sockfd;
int n;
MSG  msg;
sqlite3 *db;
int acceptfd;
pid_t pid;
char *errmsg;

if(argc != 3)
{
	printf("Usage:%s serverip  port.\n", argv[0]);
	return -1;
}
/*************************************************/
//打开数据库
if(sqlite3_open(DATABASE, &db) != SQLITE_OK)
{
	printf("%s\n", sqlite3_errmsg(db));
	return -1;
}
else
	printf("open DATABASE success.\n");

if(sqlite3_exec(db, 
			"create table if not exists usr(name text primary key,pass text);",
			//primary key主关键字只能有一个
			NULL, NULL, &errmsg) != SQLITE_OK)
{
	printf("%s\n", errmsg);
}
else
	printf("Create or open usr table success.\n");

if(sqlite3_exec(db, 
			"create table if not exists record(name text ,data text,word text);",
			NULL, NULL, &errmsg) != SQLITE_OK)
{
	printf("%s\n", errmsg);
}
else
	printf("Create or open record table success.\n");
/*************************************************/

if((sockfd = socket(AF_INET, SOCK_STREAM,0)) < 0)
{
	perror("fail to socket.\n");
	return -1;
}

struct sockaddr_in  serveraddr;
bzero(&serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
serveraddr.sin_port = htons(atoi(argv[2]));

if(bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0)
{
	perror("fail to bind.\n");
	return -1;
}

// 将套接字设为监听模式
if(listen(sockfd, 5) < 0)
{
	printf("fail to listen.\n");
	return -1;
}

//处理僵尸进程
signal(SIGCHLD,sig_child_handle);

while(1)
{
	if((acceptfd = accept(sockfd, NULL, NULL)) < 0)
	{
		perror("fail to accept");
		return -1;
	}

	if((pid = fork()) < 0)
	{
		perror("fail to fork");
		return -1;
	}
	else if(pid == 0)  // 儿子进程
	{
		//处理客户端具体的消息
		close(sockfd);
		do_client(acceptfd, db);

	}
	else  // 父亲进程,用来接受客户端的请求的
	{
		close(acceptfd);
	}
}

return 0;

}

//1登陆
int do_client(int acceptfd, sqlite3 *db)
{
MSG msg;
while(recv(acceptfd, &msg, sizeof(msg), 0) > 0)
{
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”);
}

}

printf("client exit.\n");
close(acceptfd);
exit(0);

return 0;

}

//2注册
void do_register(int acceptfd, MSG *msg, sqlite3 *db)
{
char * errmsg;
char sql[500];
int ret =-1;

sprintf(sql, "insert into usr values('%s', %s);", msg->name, msg->data);
printf("%s\n", sql);

if(sqlite3_exec(db,sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
	printf("%s\n", errmsg);
	strcpy(msg->data, "usr name already exist.");
}
else
{
	printf("client  register ok!\n");
	strcpy(msg->data, "OK!");
}

do{
	ret = send(acceptfd,msg,sizeof(MSG),0);
}while(ret <0 && EINTR==errno);
if(ret < 0)
{
	perror("fail to send");
	return ;
}

return ;

}

//3登陆
int do_login(int acceptfd, MSG *msg , sqlite3 *db)
{
char sql[500] = {};
char *errmsg;
int nrow;
int ncloumn;
char **resultp;

sprintf(sql, "select * from usr where name = '%s' and pass = '%s';", msg->name, msg->data);
printf("%s\n", sql);

if(sqlite3_get_table(db, sql, &resultp, &nrow, &ncloumn, &errmsg)!= SQLITE_OK)
{
	printf("%s\n", errmsg);
	return -1;
}
else
	printf("get_table ok!\n");

// 查询成功,数据库中拥有此用户
if(nrow == 1)
{
	strcpy(msg->data, "OK");
	send(acceptfd, msg, sizeof(MSG), 0);
	return 1;
}

if(nrow == 0) // 密码或者用户名错误
{
	strcpy(msg->data,"usr/passwd wrong.");
	send(acceptfd, msg, sizeof(MSG), 0);
}

return 0;

}

//3查询
int do_query(int acceptfd, MSG *msg , sqlite3 *db)
{
char word[64];
int found = 0;
char date[128] = {};
char sql[500] = {};
char *errmsg;

//拿出msg结构体中,要查询的单词
strcpy(word, msg->data);

found = do_searchword(acceptfd, msg, word);
printf("查询一个单词完毕.\n");

// 表示找到了单词,那么此时应该将 用户名,时间,单词,插入到历史记录表中去。
if(found == 1)
{
	//需要获取系统时间
	get_date(date);

	sprintf(sql, "insert into record values('%s','%s','%s')",msg->name,date, word);

	if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
	{
		printf("%s\n", errmsg);
		return -1;
	}
	else
	{
		printf("Insert record done.\n");
	}

}
else  //表示没有找到
	strcpy(msg->data, "Not found!");

// 将查询的结果,发送给客户端
send(acceptfd, msg, sizeof(MSG), 0);

return 0;

}

//3.1打开文件查词
int do_searchword(int acceptfd, MSG *msg, char word[])
{
FILE * fp;
int len = 0;
char temp[512] = {};
int result;
char *p;
//打开存储单词的文件
if((fp = fopen(“dict.txt”, “r”)) == NULL)
{
perror(“fail to fopen.\n”);
strcpy(msg->data, “Failed to open dict.txt”);
send(acceptfd, msg, sizeof(MSG), 0);
return -1;
}

//打印出,客户端要查询的单词
len = strlen(word);
printf("%s , len = %d\n", word, len);

//读文件,来查询单词
while(fgets(temp,512, fp) != NULL)
{
	//比较文件读到的单词前len位
	// abandon  ab
	result = strncmp(temp,word,len);
	if(result < 0)
		continue;
	//如果客户端输入的与查询到的一样
	//进一步判断避免出现查询到多个结果
	//例如查询abandon,结果出现abandonment这样结果
	if(result > 0 || ((result == 0) && (temp[len]!=' ')))
		break;
	//如果执行到这里说明
	// 找到了要查询的单词
	// 接下来就是要把单词后面的解释发送出去
	p = temp + len; //  abandon   v.akdsf dafsjkj 
	//让指针移动到解释的开头位置
	while(*p == ' ')
		p++;
	//将解释填入到消息结构体中
	strcpy(msg->data, p);
	printf("found word:%s\n", msg->data);

	// 注释拷贝完毕之后,应该关闭文件
	fclose(fp);
	return 1;
}
fclose(fp);
return 0;

}

//3.2获得日期
int get_date(char *date)
{
time_t t;
struct tm *tp;

time(&t);

//进行时间格式转换
tp = localtime(&t);

sprintf(date, "%d-%d-%d %d:%d:%d", tp->tm_year + 1900, tp->tm_mon+1, tp->tm_mday, 
		tp->tm_hour, tp->tm_min , tp->tm_sec);
printf("get date:%s\n", date);

return 0;

}

//4.查询历史
int do_history(int acceptfd, MSG *msg, sqlite3 *db)
{
char sql[128] = {};
char *errmsg;

sprintf(sql, "select * from record where name = '%s'", msg->name);

//查询数据库
if(sqlite3_exec(db, sql, history_callback,(void *)&acceptfd, &errmsg)!= SQLITE_OK)
	printf("%s\n", errmsg);
else
	printf("Query record done.\n");

// 所有的记录查询发送完毕之后,给客户端发出一个结束信息
msg->data[0] = '\0';

send(acceptfd, msg, sizeof(MSG), 0);

return 0;

}

//4.1历史结果–回调函数
// 得到查询结果,并且需要将历史记录发送给客户端
int history_callback(void* arg,int f_num,char** f_value,char** f_name)
{
// record , name , date , word
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;

}

client:
/*================================================================

  • 文件名称:在线词典客户端v1.0.c
  • 创 建 者:xiaowang
  • 创建日期:2020年04月28日
  • 描 述:

================================================================*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>

#define N 32

#define R 1 // user - register
#define L 2 // user - login
#define Q 3 // user - query
#define H 4 // user - history

// 定义通信双方的信息结构体
typedef struct {
int type;
char name[N];
char data[256];
}attribute((packed)) MSG;

int do_register(int sockfd, MSG *msg);
int do_login(int sockfd, MSG *msg);
int do_login_select(int sockfd, MSG *msg);
int do_query(int sockfd, MSG *msg);
int do_history(int sockfd, MSG *msg);

int main(int argc, const char *argv[])
{

int sockfd;
int n;
MSG  msg;

if(argc != 3)
{
	printf("Usage:%s serverip  port.\n", argv[0]);
	return -1;
}

if((sockfd = socket(AF_INET, SOCK_STREAM,0)) < 0)
{
	perror("fail to socket.\n");
	return -1;
}

struct sockaddr_in  serveraddr;
bzero(&serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
serveraddr.sin_port = htons(atoi(argv[2]));

if(connect(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0)
{
	perror("fail to connect");
	return -1;
}

char buf[100]={};
while(1)
{
	printf("*****************************************************************\n");
	printf("* 1.register          2.login              3.quit               *\n");
	printf("*****************************************************************\n");
	printf("Please choose:");

	if(1 != scanf("%d",&n)){
		puts("***输入错误重新输入");
		continue;
	}
	while(getchar() != '\n'); 

	switch(n)
	{
		case 1:
			do_register(sockfd, &msg);
			break;
		case 2:
			if(do_login(sockfd, &msg) == 1)
			{
				if(do_login_select(sockfd, &msg) == 1)
					puts("用户注销");
				else
					puts("未知错误");
			}
			break;
		case 3:
			close(sockfd);
			return 0;
			break;
		default:
			printf("输入非法命令.\n");
	}
}

return 0;

}

/注册**************************************************/

int do_register(int sockfd, MSG *msg)
{
msg->type = R;

printf("Input name:");
scanf("%s", msg->name);
getchar();

printf("Input passwd:");
scanf("%s", msg->data);
getchar();

if(send(sockfd, msg, sizeof(MSG),0) < 0)
{
	printf("fail to send.\n");
	return -1;
}

if(recv(sockfd, msg, sizeof(MSG), 0) < 0)
{
	printf("Fail to recv.\n");
	return -1;
}

// ok !  or  usr alread exist.
printf("%s\n", msg->data);

return 0;

}

/登陆*******************************/
int do_login(int sockfd, MSG *msg)
{
msg->type = L;

printf("Input name:");
scanf("%s", msg->name);
getchar();

printf("Input passwd:");
scanf("%s", msg->data);
getchar();

if(send(sockfd, msg, sizeof(MSG),0) < 0)
{
	printf("fail to send.\n");
	return -1;
}

if(recv(sockfd, msg, sizeof(MSG), 0) < 0)
{
	printf("Fail to recv.\n");
	return -1;
}

if(strncmp(msg->data, "OK", 3) == 0)
{
	printf("Login ok!\n");
	return 1;
}
else 
{
	printf("%s\n", msg->data);
}

return 0;

}

/登录选项***************************************/
int do_login_select(int sockfd, MSG msg)
{
int n = -1;
while(1)
{
printf("*****************************************************\n");
printf("
1.query_word 2.history_record 3.quit *\n");
printf("*****************************************************\n");
printf(“Please choose:”);
if(1 != scanf("%d",&n)){
puts("***输入错误重新输入");
continue;
}
while(getchar() != ‘\n’);

	switch(n)
	{
		case 1:
			do_query(sockfd, msg);
			break;
		case 2:
			do_history(sockfd, msg);
			break;
		case 3:
			return 1;
			break;
		default :
			printf("***输入非法.\n");
	}

}
return 0;

}

/查询************************************/
int do_query(int sockfd, MSG *msg)
{
msg->type = Q;
puts("--------------");

while(1)
{
	printf("Input word:");
	scanf("%s", msg->data);
	getchar();

	//客户端,输入#号,返回到上一级菜单
	if(strncmp(msg->data, "#", 1) == 0)
		break;

	//将要查询的单词发送给服务器
	if(send(sockfd,msg, sizeof(MSG), 0) < 0)
	{
		printf("Fail to send.\n");
		return -1;
	}

	// 等待接受服务器,传递回来的单词的注释信息
	if(recv(sockfd, msg,sizeof(MSG), 0) < 0)
	{
		printf("Fail to recv.\n");
		return -1;
	}
	printf("%s\n", msg->data);
}
return 0;

}

/历史***********************************/
int do_history(int sockfd, MSG *msg)
{

msg->type = H;

send(sockfd, 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;

}

Makefile:
all:
gcc server.c -o server -lsqlite3
gcc client.c -o client
.PHONY:clean
clean:
rm server client my.db

还要有字典数据库,自己网上下载


本文链接: http://www.dtmao.cc/news_show_200382.shtml

附件下载

相关教程

    暂无相关的数据...

共有条评论 网友评论

验证码: 看不清楚?