接触到的基于Linux的第一个实战小项目,在众多大牛的协助下完美实现。

在线词典功能的实现
1、用户的注册
2、用户登录
3、单词的查询
4、历史记录的查看
5、用户在登录后修改密码

头文件

#ifndef COMM_HH
#define COMM_HH#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <pthread.h>
#include <pthread.h>
#include <stdlib.h>
#include <sqlite3.h>
#include <signal.h>
#include<time.h>#define MSGTYPE_R  01 //用户注册
#define MSGTYPE_L  02 //用户登录
#define MSGTYPE_Q  03 //用户查询
#define MSGTYPE_H  04//用户历史记录
#define MSGTYPE_C  05//用户修改密码#define DATABASE "lict.db"typedef struct msg_struct{char cmd;        //1-register 2-log 3-exit 4-dic 5-history 6-passwd    12.服务器应答char name[32];char passwd[16];char new_passwd[16];char data[256];  int type;//以下是服务器的回应char ret;  //0-success  errno-失败原理char response[128];
}MSG_T;#endif

客户端的实现

#include "comm.h"int do_register(int socket_cli, MSG_T *msg)//客户端注册
{printf("用户注册注册中   ... \n");int ret;memset(msg, 0, sizeof(MSG_T));msg->type = MSGTYPE_R;//11;printf("请输入账号:"); scanf("%s", msg->name); getchar();printf(" ________________\n");printf("请输入密码:"); scanf("%s", msg->data); getchar();ret=send(socket_cli, msg, sizeof(MSG_T), 0);if (ret < 0){perror("send err");printf("注册信息发送失败.\n");return -1;}if (recv(socket_cli, msg, sizeof(MSG_T), 0) < 0){printf("注册失败.\n");return -1;}printf("%s\n", msg->data);return 1;
}int do_login(int socket_cli, MSG_T *msg)// 登录, 必服务器返回 "OK" 才表示登录成功
{printf("正在登录 ...\n");memset(msg, 0, sizeof(MSG_T));msg->type = MSGTYPE_L;printf("  请输入账号:"); scanf("%s", msg->name); getchar();printf(" ---------------\n");printf("  请输入密码:"); scanf("%s", msg->data); getchar();if (send(socket_cli, msg, sizeof(MSG_T), 0) < 0){printf("请重新登录\n");return -1;}if (recv(socket_cli, msg, sizeof(MSG_T), 0) < 0){printf("登录失败 !\n");return -1;}//登录成功if (strncmp(msg->data, "OK", 3) == 0){printf("登录成功 ! \n");memset(msg, 0, sizeof(MSG_T));return 1;}else{printf("%s\n", msg->data);}return 0;
}int do_change(int socket_cli, MSG_T *msg)//修改用户密码
{printf("正在修改用户密码,务必确认本人操作   \n");int ret;memset(msg, 0, sizeof(MSG_T));msg->type = MSGTYPE_C;printf("请输入账号:"); scanf("%s", msg->name); getchar();printf(" ________________\n");printf("请输入密码:"); scanf("%s", msg->data); getchar();printf("\n");printf(" ________________\n");printf("请输入新密码:"); scanf("%s", msg->new_passwd); getchar();ret=send(socket_cli, msg, sizeof(MSG_T), 0);if (ret < 0){perror("send err");printf("修改请求发送失败.\n");return -1;}memset(msg, 0, sizeof(MSG_T));if (ret =0){perror("change err");printf("密码修改成功\n");return -1;}if (recv(socket_cli, msg, sizeof(MSG_T), 0) < 0){printf("修改失败.\n");return -1;}return 1;
}int do_query(int socket_cli, MSG_T *msg) // 单词查询
{printf("查询中 ...\n");recv(socket_cli, msg, sizeof(MSG_T), 0);memset(msg, 0, sizeof(MSG_T));msg->type = MSGTYPE_Q;while(1){printf("请输入单词:"); scanf("%s", msg->data); getchar();if (strncmp(msg->data, "*", 1) == 0)break;//退出if (send(socket_cli, msg, sizeof(MSG_T), 0) < 0){printf("发送失败\n");return -1;}memset(msg, 0, sizeof(MSG_T));if (recv(socket_cli, msg, sizeof(MSG_T), 0) < 0){perror("接收失败");return -1;}printf("%s\n", msg->data);}return 1;
}int do_history(int socket_cli, MSG_T *msg)  // 历史记录查询
{printf("...历史记录 ...\n");msg->type = MSGTYPE_H;//将消息发送给服务器if (send(socket_cli, msg, sizeof(MSG_T), 0) < 0){printf("发送失败\n");return -1;}while(1){if (recv(socket_cli, msg, sizeof(MSG_T), 0) < 0){printf("接收失败\n");return -1;}if (msg->data[0] == '\0')break;printf("%s\n", msg->data);}return 1;}int main(int argc, const char *argv[])
{struct sockaddr_in server_addr;int input_nbr;MSG_T send_msg;MSG_T                  msg;int socket_cli = socket(AF_INET,SOCK_STREAM, 0 );if(socket_cli <0){perror("create client socket err");return -3;}struct sockaddr_in  serv_addr;serv_addr.sin_family = AF_INET;serv_addr.sin_port = htons(10050); serv_addr.sin_addr.s_addr = INADDR_ANY;//inet_addr("192.168.17.129"); int ret = connect(socket_cli,(struct sockaddr *)&serv_addr,sizeof(serv_addr));if(ret <0){perror("connect err");return -3;} struct msg_struct cli_msg;while (1){printf(" ______________________________________________\n");printf(" ______________________________________________\n");printf(" ________                               ________\n");printf(" ________  1.注册   2.登录    3.退出    ________\n");printf(" ______________________________________________\n");printf(" ______________________________________________\n");printf(" ______________________________________________\n");printf("\n");printf("请选择:");scanf("%d", &input_nbr);getchar();//回收垃圾字符switch (input_nbr){case 1:do_register(socket_cli, &send_msg);break;case 2:if (do_login(socket_cli, &send_msg) ==1 ){goto _login;}break;case 3:close(socket_cli);exit(0);break;default:printf("Invalid data cmd. \n");break;}}_login:while(1)//登录后的界面{printf(" ______________________________________________\n");printf(" ______________________________________________\n");printf("\n");printf("1.查询(*退出)  2.历史查询  3.退出   4.修改用户密码    \n");printf(" ______________________________________________\n");printf(" ______________________________________________\n");printf("\n");printf("请选择:");input_nbr = 0;scanf("%d", &input_nbr);getchar();switch (input_nbr){case 1:do_query(socket_cli, &send_msg);break;case 2:do_history(socket_cli, &send_msg);break;case 3:close(socket_cli);exit(0);break;/*case 4:do_change(socket_cli, &send_msg);exit(0);break;*/default:printf("Invalid data cmd. \n");break;}}return 0;}

服务器的实现

#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <pthread.h>
#include <pthread.h>
#include <stdlib.h>
#include <sqlite3.h>
#include <signal.h>
#include<time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <sys/types.h>
#include <sys/socket.h>#include "comm.h"static int cnt=1;
static int num=0;
static int s=0;
static int n=0;
static int ave;struct thread_msg{int cli_socket;pthread_t tid;};sqlite3 *db = NULL;int do_query(int socket_cli, MSG_T *msg, sqlite3 *db);
int do_login(int socket_cli, MSG_T *msg, sqlite3 *db);
int do_history(int socket_cli, MSG_T *msg, sqlite3 *db);
void get_date(char *data);int print(void *para,int f_num,char **f_value,char **f_name)
{int i;if(cnt){printf("--------------------------------------------------\n");cnt--;for(i=0;i<f_num;i++){printf("%-12s",f_name[i]);}printf("\n");printf("--------------------------------------------------\n");}for(i=0;i<f_num;i++){printf("%-12s",f_value[i]);}printf("\n");printf("--------------------------------------------------\n");return 0;
}
int do_register(int socket_cli, MSG_T *msg, sqlite3 *db) //用户注册
{char sql[128] = {0};int ret;snprintf(sql,sizeof(sql), "insert into user values('%s', '%s');", msg->name, msg->data );ret = sqlite3_exec(db,sql,print,NULL,NULL);if (ret!= SQLITE_OK){printf("%s\n",sqlite3_errmsg(db));memset(msg->data, 0, strlen(msg->data));snprintf(msg->data, sizeof (msg->data),"用户: %s 已存在!", msg->name);}else{printf( "客户(%s)注册成功\n",msg->name  );memset(msg->data, 0, strlen(msg->data));strcpy(msg->data, "register ok!");}//返回应答ret=send(socket_cli, msg, sizeof(MSG_T), 0);if(ret<0){printf("发送失败\n");return 0;}return 1;
}void *serv_for_client(void *args)
{int ret;struct thread_msg *pmsg = args;int socketx = pmsg->cli_socket;struct msg_struct serv_msg;while(1){memset(&serv_msg,0,sizeof(serv_msg));ret = recv(socketx,&serv_msg,sizeof(serv_msg),0);if(ret<0){perror("recv err"); close(socketx); free(pmsg); return NULL;}else if(ret == 0){printf("serv found peer shutdwon\n"); close(socketx); free(pmsg); return NULL;}printf("%s->%d\n",__func__,__LINE__);switch(serv_msg.type){case  01:             //MSGTYPE_Rdo_register(socketx, &serv_msg, db);break;case  02:                 //MSGTYPE_L:do_login(socketx, &serv_msg, db);break;case  03:               //MSGTYPE_Q:do_query(socketx, &serv_msg, db);break;case  04:                  //MSGTYPE_H:do_history(socketx, &serv_msg, db);break;default:printf("invalid data msg.\n");}ret = send(socketx,&serv_msg,sizeof(serv_msg),0);if(ret<0){perror("send err");  return NULL;}}/*while (recv(socketx, &serv_msg, sizeof(MSG_T), 0) > 0){}printf("client exit.\n");close(socketx);exit(0);return 0;*/close(socketx);return NULL;
}int do_login(int socket_cli, MSG_T *msg, sqlite3 *db)//用户登录
{char sql[128] = {0};char *errmsg = NULL, **result = NULL;int nrow, ncolumn,ret;snprintf(sql,sizeof(sql), "select * from user where name='%s' and passwd='%s';", msg->name, msg->data);ret=sqlite3_get_table(db, sql, &result, &nrow, &ncolumn, &errmsg) ;if (ret != SQLITE_OK){printf("sqlite3_exec():%s\n",sqlite3_errmsg(db));}else{printf("表格获取成功\n");}if (nrow == 1)//查询成功,数据库中拥有此用户{printf("用户:%s登录成功\n", msg->name);memset(msg->data, 0, strlen(msg->data));strcpy(msg->data, "OK");}else //用户名或密码错误{printf("用户:(%s) 登录失败! \n", msg->name);perror("login err");memset(msg->data, 0, strlen(msg->data));strcpy(msg->data, "账号或密码错误! \n");}//返回应答ret=send(socket_cli, msg, sizeof(MSG_T), 0);if (ret<0){perror("发送失败\n");return 0;}return 1;
}int do_searchword(MSG_T *msg, char *word)//根据单词从dirt.txt文本中查找对应的注释信息
{FILE *fp = NULL;int word_len = strlen(word);char row_data[512] = {'\0'};int res = 0;int ret;char *p; //指向注释fp = fopen("dict.txt", "r")  ;//打开词典文件if (fp==NULL){perror("fail to open dict.txt.\n");return -1;}//打印客户端要查询的单词word_len = strlen(word);printf("%s, len = %d\n", word, word_len );while (fgets(row_data, 512, fp) != NULL){res = strncmp(row_data, word, word_len);//每行对比前word_len个字节if (res != 0)continue;if (row_data[word_len] != ' ') //单词跟注释之间没有空格goto _end;p = row_data + word_len;// 找到了单词,跳过所有的空格while (*p == ' '){p++;}strcpy(msg->data, p);fclose(fp);return 1;}_end:fclose(fp);return 0; //文件对比完,单词未找到
}int do_query(int socket_cli, MSG_T *msg, sqlite3 *db)  // 单词查询
{char sql[128] = {0};char word[64] = {0};int found = 0;char date[128] = {0};char *errmsg;int ret;printf("\n");//单词查找strcpy(word, msg->data);//memset(msg->data, 0, strlen(msg->data));found = do_searchword(msg, word);//调用函数if (found == 1) {get_date(date);//获取系统时间snprintf(sql, 128,"insert into record values('%s', '%s', '%s')", msg->name, date, word);ret=sqlite3_exec(db, sql,print, NULL, NULL );if (ret != SQLITE_OK){printf("sqlite3_exec():%s\n",sqlite3_errmsg(db));return -1;}}else if (found == 0)//没有找到{memset(msg->data, 0, strlen(msg->data));strcpy(msg->data, "单词未找到!\n");}else if (found == -1)//dict.txt代开失败{memset(msg->data, 0, strlen(msg->data));strcpy(msg->data, "打开 dict.txt.失败了");}send(socket_cli, msg, sizeof(MSG_T), 0);//将查询的结果发送给客户端return 0;
}int history_callback(void* arg,int colCount,char** colValue,char** colName)// 得到查询结果,并且需要将历史记录发送给客户端
{int socketx;MSG_T msg;socketx = *((int *)arg);sprintf(msg.data, "%s , %s", colValue[1], colValue[2]);send(socketx, &msg, sizeof(MSG_T), 0);return 0;
}int do_history(int socket_cli, MSG_T *msg, sqlite3 *db)// 历史记录查询
{char sql[128] = {0};char *errmsg;int ret;sprintf(sql, "select * from record where name = '%s'", msg->name);ret=sqlite3_exec(db, sql, history_callback,(void *)&socket_cli,NULL );if(ret!= SQLITE_OK){printf("sqlite3_exec():%s\n",sqlite3_errmsg(db));}else{printf("sqlite3 query record done.\n");}msg->data[0] = '\0';// 所有的记录查询发送完毕之后,给客户端发出一个结束信息ret = send(socket_cli, &msg, sizeof(MSG_T), 0);if(ret<0){perror("histroy send err");return -34;}return 0;
}int do_change(int socket_cli, MSG_T *msg, sqlite3 *db) //修改用户密码
{char sql[128] = {0};int ret;char **pt=NULL;int nrow,ncolumn;snprintf(sql,sizeof(sql), "select from user where user=\'%S\' and passwd=\'%s\';", msg->name, msg->data );//查看数据库是否存在ret = sqlite3_get_table(db,sql,&pt,&norm,&ncolumn,NULL);if (ret){printf("gettabale err%s\n",sqlite3_errmsg(db));return -2;}if(nrow!=0){char **pt=NULL;snprintf(sql,sizeof(sql), "updata user set passwd=\'%S\' and passwd=\'%s\';", msg->name, msg->data );//修改数据库中用户密码ret = sqlite3_get_table(db,sql,&pt,NULL,NULL,NULL);if (ret){printf("recv gettabale err%s\n",sqlite3_errmsg(db));return -2;}printf("密码修改成功");strcpy(msg->data, "修改成功!");ret = send(socket_cli, &msg, sizeof(MSG_T), 0);if(ret<0){perror("change send err");return -34;}}else{strcpy(msg->data, "输入有误!"); ret=send(socket_cli, msg, sizeof(MSG_T), 0);if(ret<0){perror("change send err");return -34;memset(msg->data, 0, strlen(msg->data));}//返回应答if(ret<0){printf("发送失败\n");return 0;}return 1;
}void get_date(char *data)//获取系统时间
{time_t rowtime;struct tm *info;time(&rowtime);info = localtime(&rowtime);sprintf(data, "%d-%d-%d %d:%d:%d", info->tm_year + 1900, info->tm_mon + 1, info->tm_mday,info->tm_hour, info->tm_min, info->tm_sec);                                  printf("get date is : %s\n", data);
}int main(int argc, const char *argv[])
{int ret;int socket_cli ;struct sockaddr_in server_addr;struct sockaddr_in client_addr;socklen_t addrlen = sizeof(client_addr);char sql[128] = {0};pid_t pid;char ipv4_addr[16];/*********************数据库操作*********************/ret = sqlite3_open("./dict.db",&db);if(ret){printf("sqlite3_open():%s\n",sqlite3_errmsg(db));exit(-1);}printf("sqlite3 open %s success.\n", DATABASE);//snprintf(sql,128, "");sqlite3_exec(db, sql, print ,NULL, NULL );if(ret != SQLITE_OK){printf("sqlite3_exec():%s\n",sqlite3_errmsg(db));return -1;}memset(sql, 0, sizeof(sql));sprintf(sql,  "    "   );ret=sqlite3_exec(db, sql, print , NULL, NULL  );//打开记录表if (ret != SQLITE_OK){printf("%s\n", sqlite3_errmsg(db));return -1; }/*********************网络通信*********************/int main_socket=socket(AF_INET,SOCK_STREAM,0);if(main_socket<0){perror("crreat main_socket err");return -5;}int enable=1;setsockopt(main_socket,SOL_SOCKET,SO_REUSEADDR,&enable,sizeof(enable));struct sockaddr_in serv_addr;serv_addr.sin_family=AF_INET;   serv_addr.sin_port=htons(10050);serv_addr.sin_addr.s_addr=INADDR_ANY;ret=bind(main_socket,(struct sockaddr*)&serv_addr,sizeof(serv_addr));if(ret<0){perror("bind err");return -15;}ret = listen(main_socket,5);if(ret<0){perror("listen err");return -3;}struct sockaddr_in cli_addr;addrlen=sizeof(cli_addr);struct thread_msg*pmsg=NULL;int socket_new;int cli_socket1;
loop:cli_socket1=accept(main_socket,(struct sockaddr*)&cli_addr,&addrlen);if(cli_socket1<0){perror("accept err");return -5;}pmsg=malloc(sizeof(*pmsg));pmsg->cli_socket=cli_socket1;pthread_create( &pmsg->tid,NULL,serv_for_client, pmsg );goto loop;close(main_socket);return 0;
}

运行结果

服务器:

客户端:

基于Linux的小项目-在线词典相关推荐

  1. 基于安卓app开发项目(在线数独对战游戏平台)的毕业设计(附源码)

    大家好!我是职场程序猿,感谢您阅读本文,欢迎一键三连哦. 基于安卓app开发项目(在线数独对战游戏平台)的毕业设计 目录 一.项目简介 二.系统核心功能模块部分截图 2.1用户登陆的设计与实现 2.2 ...

  2. Andriod小项目——在线音乐播放器

    Andriod小项目--在线音乐播放器 转载请注明:http://blog.csdn.net/sunkes/article/details/51189189 Android在线音乐播放器 从大一开始就 ...

  3. Linux多进程编程之在线词典

    在线词典是基于Linux 多进程并发服务器编程,由服务器端和客户端构成,客户端可以运行在多个不同的主机上连接服务器,服务器对员工信息的操作结果通过数据库sqlite来保存.当用户登录后,根据用户名判断 ...

  4. 《基于Linux物联网综合项目》常见问题汇总fae

    关于该课程说明 1)本课程目标 通过web浏览器访问服务器,实现登录.注册.数据库操作.远程操控硬件.采集环境信息.远程监控.拍照.图片显示等功能. 将单片机.linux.html.摄像头.数据库等知 ...

  5. C小项目——电子词典

    C语言项目--查字典 宗旨:技术的学习是有限的,分享的精神是无限的. [项目需求描述] 一.单词查询 给定文本文件"dict.txt",该文件用于存储词库.词库为"英-汉 ...

  6. Linux C小项目 —— 简单的web服务器

    简单的Web服务器 实现一个基于HTTP通信协议的web服务器.客户端向服务器程序发送所需文件的请求,服务器端分析请求并将文件发送个客户端. 1.整体程序设计 客户端发送所需文件,服务器返回该文件,通 ...

  7. 基于Linux的Qt项目在windows下发布

    QT在Linux下的界面处理人所共知,现在有个需求是一定要在windows下做界面,时间比较紧.目前已经在Linux下的界面如何port至windows呢? 这里用到QT的跨平台.这种时候使用qt+m ...

  8. 基于Javaweb的小项目(类似于qqzone)1——设计数据库

    1.熟悉QQZone业务需求 1)用户登录 2)登录成功,显示主界面,左侧显示好友列表:上端显示欢迎词:如果不是自己的空间,显示超链接,返回自己的空间:下端显示日志列表 3)查看日志详情: 日志本身的 ...

  9. 基于Javaweb的小项目(类似于qqzone) 7 —— 日志相关操作

    功能描述 展示日志详情:点击日志列表中的某个日志标题,可展示该日志的详情信息 -在展示日志详情信息的下面,还要展示其他人对此日志的回复 -若该回复存在主人回复,则也需要显示主人回复 添加日志:点击发表 ...

  10. 基于Javaweb的小项目(类似于qqzone) 2 ——服务端连接数据库并实现CRUD的通用操作

    1.数据库连接与关闭 服务端使用Druid连接池进行数据库连接,主要分为两步: 1.配置jdbc.properties文件 driverClassName=com.mysql.jdbc.Driver ...

最新文章

  1. 每日记载内容总结44
  2. C++ 循环链表练习题 报数删除【非常没有条理】
  3. 基本概念学习(8000)---兼容机
  4. 『设计模式』80年代的人们就已经领悟了设计模式-- 发布者/订阅者模式 (包括发布者/订阅者模式和观察者模式的区别)
  5. 程序员永远的痛之字符编码的奥秘
  6. 使用kubeadm安装kubernetes1.12.2版本脚本
  7. ADO.Net之SqlConnection、 Sqlcommand的应用(读书笔记1)
  8. 泰山站和泰安站怎么区分?
  9. java中动态代理的使用
  10. 运维讨厌流浪地球的原因
  11. Windows 8 Consumer Preview
  12. Improving Opencv 4: The Core Functionality :Operations with images
  13. 数据库服务器系统崩溃,mssql数据库系统崩溃后的一般处理步骤与方法
  14. DevExpress WPF初级教程 - 图像选择器的使用
  15. 2012 windows 端口聚合_如何在WindowsServer2012中实现NIC组合
  16. 西南交大计算机第3次作业答案,西南交大大学英语I第3次作业题答案
  17. ImportError: DLL load failed while importing qhull:问题解决
  18. 理解表现和结构相分离
  19. js通过IP地址获取所在城市
  20. PTA 古风排版 (20 分)队列方法

热门文章

  1. java实现KMZ文件转KML文件
  2. android 计算器边框,Android计算器——入门
  3. sht21 c语言程序,湿度传感器SHT21示例代码-SampleCodeforSHT21.PDF
  4. 中交四航局及中广核工程公司学员参加友勤第12期Oracle P6项目管理软件培训班
  5. Sonar 下载及结合maven使用
  6. CGJ02、BD09、西安80、北京54、CGCS2000常用坐标系详解
  7. 2021华为软件精英挑战赛
  8. Linux 大小端转换函数
  9. visio2019画电路图(论文)
  10. 华为综合实验——ISIS-BGP