初探Linux网络编程:在线英语词典的实现

打印 上一主题 下一主题

主题 985|帖子 985|积分 2957



闲话少说

此文章为在线英语词典实现,第一次基本独立做项目,大部门功能没题目,不敷的是代码冗余有点多,还可能有些小BUG。
仅做记载并且分享本身学习Linux网络编程的过程,学艺不精,code新人,如有错误接待在评论区讨论、指正!,若文章内容对你有帮助,希望可以给我点个赞!

1. 思路构筑(想框架,理流程)

做完本次项目,进一步体会到思路构筑的重要性;若你向我一样经验不敷,最好不要脑子一热就狂写一堆,到了项目做到一半发现要大改……说多都是泪。这部门多花时间一点也无妨。
先来看一下做该项目的大致思路:写好大致框架后,一个模块一个模块的添,模块边写边测试。“让服务器做所有事变” 这种想法是大忌。 有些事变让客户端去做会大大降低你项目编码的难度。二者如何分工,请看下文。
1.1 大致思路

1.1.1 功能模块



  • 用户界面:告诉用户可以做些什么事变
  • 账号操作:登录或注册
  • 查询操作:查询单词或者成功查询的历史
1.1.2 服务器



  • 一个数据库,数据库内三张表user, word, history ,分别存放用户,单词,和成功查询单词历史信息
  • 接收请求

    • 1.注册:得到用户 id pwd 并添加到 user 表中
    • 2.登录:得到用户 id pwd 到 user 表中比对 id 和 pwd
    • 3.查单词:得到用户输入单词,到 word 表中查找
    • 4.查历史:根据用户 id,到 history 中查找记载

  • 返回相应结果
1.1.3 客户端



  • 用户界面:提示用户当前可以做什么事变
  • 得到用户请求,并发送给服务器
  • 接收回复结果,做相应处理
1.1.4 交互流程

该项目简单来说就是:用户只有在登录成功之后才可以进入查询环节;进入查询环节之后可以不停查询,直到用户在“查单词“环节输入 ”Q“ 之后才会回退到账号界面。
固然这并不灵活,是后续可以改进的点。
   

  服务器启动的条件下,用户运行客户端,输入数字(1, 2, 3, 4)即可做对应的事变。
数字对应功能如下图所示
   账号界面

  查询界面

  
2. 代码

2.1 部门效果展示

   登录成功

单词查询结果

历史查询结果,打印有点小题目

  2.2 项目概况 readMe.txt

服务器端


  • 主函数 server.c
  • 功能函数 tool.c
  • 编译下令: gcc server.c tool.c -lsqlite3 -o server
  • 运行下令: ./server IP port
  • 初次运行下令: ./server IP port num --> num 任意数字即可
  • 词典数据文件:dict.txt
客户端


  • 主函数 client.c
  • 功能函数 tool.c
  • 编译下令: gcc clien.c tool.c -lsqlite3 -o client
  • 运行下令: ./client IP port
2.3.头文件 tool.h

包罗了客户端和服务器需要用到的所有功能模块函数接口(并不是很好,最好客户端和服务器模块功能函数分开放)
  1. #ifndef _TOOL_H_
  2. #define _TOOL_H_
  3. #include <stdio.h>
  4. #include <sys/types.h>
  5. #include <sys/socket.h>
  6. #include <arpa/inet.h>
  7. #include <signal.h>
  8. #include <wait.h>
  9. #include <time.h>
  10. #include <sqlite3.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <unistd.h>
  14. #define R 1 // register
  15. #define L 2        // login
  16. #define C 3 // check
  17. #define H 4        // history
  18. #define Q 5 // quit
  19. #define GET_ID_ERR 6        //获取id 失败
  20. #define GET_PWD_ERR 7        //获取pwd 失败
  21. #define ID_ERR 8        // 用户id 错误
  22. #define PWD_ERR 9        // 用户pwd 错误
  23. //用户界面
  24. void UI_account(void);
  25. //查询界面
  26. void UI_check(void);
  27. // 初始化数据库,只是准备,后续使用仍需要手动打开
  28. int database_init(char *dbname);
  29. // 注册
  30. int user_add(int connfd, sqlite3 *db);
  31. // 登陆
  32. int user_login(int connfd, sqlite3 *db);
  33. // 查单词
  34. int check(int connfd, sqlite3 *db, int id);
  35. // 成功历史查询
  36. int history(int connfd, sqlite3 *db, int id);
  37. // 定义用户帐号函数,登陆成功返回用户id
  38. int account(int connfd, sqlite3 *db,int mode);
  39. // 行为函数
  40. int operation(int connfd, sqlite3 *db, int mode, int id);
  41. // 服务器初始化
  42. int server_init(char *ip, char* port);
  43. #endif
复制代码
2.4 功能函数 tool.c

  1. #include "tool.h"
  2. //帐号界面
  3. void UI_account(void){
  4.         char buf[512] = {0};
  5.         strcat(buf,"******************************************\n");
  6.         strcat(buf,"*                                        *\n");
  7.         strcat(buf,"*     **     输入数字即可开始    **      *\n");
  8.         strcat(buf,"*                                        *\n");
  9.         strcat(buf,"*            1:注册   2:登陆             *\n");
  10.         strcat(buf,"*                                        *\n");
  11.         strcat(buf,"******************************************\n");
  12.         printf("%s", buf);
  13. }
  14. // 查询界面
  15. void UI_check(void){
  16.         char buf[512] = {0};
  17.         strcat(buf,"******************************************\n");
  18.         strcat(buf,"*                                        *\n");
  19.         strcat(buf,"*     **    输入数字即可开始    **       *\n");
  20.         strcat(buf,"*                                        *\n");
  21.         strcat(buf,"*        3:查单词      4:历史查询        *\n");
  22.         strcat(buf,"*                                        *\n");
  23.         strcat(buf,"******************************************\n");
  24.         printf("%s", buf);
  25. }
  26. // 初始化数据库,只是准备,后续使用仍需要手动打开
  27. int database_init(char *dbname)
  28. {
  29.         puts("---             服务器初始化中,请稍候...           ---");
  30.         char sql[256] = {0};
  31.         sqlite3 *db;
  32.         if(-1 == sqlite3_open(dbname, &db)){
  33.                 printf("%s open error: %s\n", dbname, sqlite3_errmsg(db));
  34.                 return -1;
  35.         }
  36.         /*------------------------------------------------------------------------*/
  37.         // 初始化 user(id int primary key, password int)
  38.         strcpy(sql, "create table if not exists user(id int primary key,\
  39.                 password int)");
  40.         if(0 != sqlite3_exec(db, sql, NULL, NULL, NULL)){
  41.                 printf("user create error: %s\n", sqlite3_errmsg(db));
  42.                 return -1L;
  43.         }
  44.         /*------------------------------------------------------------------------*/
  45.         // 创建 word 数据库
  46.         strcpy(sql, "create table if not exists word(word str(15),\
  47.                 meaning text)");
  48.         if(0 != sqlite3_exec(db, sql, NULL, NULL, NULL)){
  49.                 printf("word create error: %s\n", sqlite3_errmsg(db));
  50.                 return -1;
  51.         }
  52.         //词典文件上传到数据库
  53.         FILE *fp = fopen("dict.txt", "r+");
  54.         if(NULL == fp){
  55.                 perror("dict fopen");
  56.                 return -1;
  57.         }
  58.         char buf[64] = {0};//词条
  59.         char word[32] = {0}; //单词
  60.         while(fgets(buf, sizeof(buf), fp)){
  61.                 //把单词从词条中提取出来
  62.                 char *cut = strstr(buf, " ");
  63.                 strncpy(word, buf, cut-buf);
  64.                 //单词和词条添加到数据库word中
  65.                 char sql[128] = {0};
  66.                 sprintf(sql, "insert into word values('%s', '%s')",word, buf);
  67.                 if(0 != sqlite3_exec(db, sql, NULL, NULL, NULL)){
  68.                         printf("word insert: %s\n", sqlite3_errmsg(db));
  69.                         return -1;
  70.                 }
  71.                 memset(buf, 0, sizeof(buf));
  72.                 memset(word, 0, sizeof(word));
  73.         }
  74.         /*------------------------------------------------------------------------*/
  75.         // 初始化 history(id int primary key, word str(40), time text)
  76.         strcpy(sql, "create table if not exists history(id int,\
  77.                 word str(40), time text)");
  78.         if(0 != sqlite3_exec(db, sql, NULL, NULL, NULL)){
  79.                 printf("history create error: %s\n", sqlite3_errmsg(db));
  80.                 return -1;
  81.         }
  82.         sqlite3_close(db);
  83.         return 0;
  84. }
  85. /*------------------------------------------------------------------------*/
  86. // 注册
  87. int user_add(int connfd, sqlite3 *db){
  88.         // id是主键,sqlite3会判断 id 唯一性,所以这里不用
  89.         int id, pwd;
  90.         char sql[128] = {0};
  91.         char buf[128] = {0};
  92.         // 接受数据,拼接sql语句
  93.         recv(connfd, (void*)&id, sizeof(id), 0);
  94.         recv(connfd, (void*)&pwd, sizeof(pwd), 0);
  95.        
  96.         if(9 >= id)
  97.                 return ID_ERR;// id 不合法
  98.         sprintf(sql, "insert into user values(%d,%d);", id, pwd);
  99.         if(0 != sqlite3_exec(db, sql, NULL, NULL, NULL)){
  100.                 printf("add user error: %s\n", sqlite3_errmsg(db));
  101.                 return ID_ERR;
  102.         }
  103.         // 注册成功
  104.         printf("用户id:%d  pwd:%d 注册成功!\n",id, pwd);
  105.         return 0;
  106. }
  107. /*------------------------------------------------------------------------*/
  108. // 登陆, 登陆成功返回用户id
  109. int user_login(int connfd, sqlite3 *db){
  110.         int id, pwd;
  111.         char **result;
  112.         int row, col;
  113.         char buf[128] = {0};
  114.         char sql[128] = {0};
  115.         // 获取登陆用户输入的id pwd
  116.         int ret = recv(connfd, &id, sizeof(id), 0);
  117.         if(-1 == ret){
  118.                 perror("获取登陆用户id 失败");
  119.                 return GET_ID_ERR;
  120.         }else if(0 == ret){
  121.                 printf("客户端退出\n");
  122.         }
  123.         ret = recv(connfd, &pwd, sizeof(pwd), 0);
  124.         if(-1 == ret){
  125.                 perror("获取登陆用户pwd 失败");
  126.                 return GET_PWD_ERR;
  127.         }else if(0 == ret){
  128.                 printf("客户端退出\n");
  129.         }
  130.         //判断登陆id合法性
  131.         if(9 >= id){
  132.                 return ID_ERR;//不合法
  133.         }
  134.         printf("已登陆用户-----id: %d, pwd: %d\n", id, pwd);
  135.         // 查看 user 表中是否有该用户       
  136.         sprintf(sql, "select * from user where id = %d", id);
  137.         if(0 != sqlite3_get_table(db, sql, &result, &row, &col, NULL)){
  138.                 printf("login user error: %s\n", sqlite3_errmsg(db));
  139.                 return ID_ERR;//用户不存在
  140.         }
  141.         for(int i=1; i<=row; i++){
  142.                 for(int j=0; j<col;j++){
  143.                         //判断用户id
  144.                         if(id == atoi(result[i * col + j])){
  145.                                 //判断用户密码
  146.                                 if(pwd == atoi(result[i*col+j+1])){
  147.                                         return id;
  148.                                 }else{
  149.                                         return PWD_ERR;
  150.                                 }
  151.                         }
  152.                 }
  153.         }
  154.         return -1;
  155. }
  156. /*------------------------------------------------------------------------*/
  157. // 可查一次查单词, 且上传成功查询历史
  158. // 返回值:正常查询发送信息给客户端,返回 0 ;出错 -1
  159. int check(int connfd, sqlite3 *db, int id){
  160.         char **result;
  161.         int row, col;
  162.         char sql[128] = {0};
  163.         char buf[128] = {0};
  164.         // 提取 word 表的数据
  165.         strcpy(sql, "select * from word");
  166.         if(0 != sqlite3_get_table(db, sql, &result, &row, &col, NULL)){
  167.                 return -1;
  168.         }
  169.         //获得用户单词信息
  170.         char input[32] = {0};
  171.         recv(connfd, input, sizeof(input), 0);
  172.         int input_len = strlen(input);
  173.         printf("客户端获得单词:%s\n", input);
  174.         // 得到Q退出
  175.         if(0 == strncmp(input, "Q", 1)){
  176.                 return Q; //
  177.         }
  178.         //判断word
  179.         int index = col;//查询所用下标,因为 col 等于字段数
  180.         int flag = 0;//标记单词查询状态 0:未找到  1:找到
  181.         int max = row*col-2; //单词以及解释的总个数, 2 是字段数 word, meaning
  182.         for(int i=0; i<=row; i++){
  183.                 if(1 == flag)//找到直接退出循环
  184.                         break;
  185.                 for(int j=0; j<col;j++){
  186.                         //接收数据库数据(否则无法获取单词真正长度)
  187.                         char word[20] = {0};
  188.                         strcpy(word, result[index]);
  189.                         int word_len = strlen(word);
  190.                         //判断单词内容与单词长度
  191.                         if(input_len == word_len && 0 == strncmp(input, result[index], strlen(input))){
  192.                                 // 成功查到发送解释 result[index+1]
  193.                                 sprintf(buf, "%s", result[index+1]);
  194.                                 send(connfd, buf, strlen(buf), 0);
  195.                                 memset(buf, 0, sizeof(buf));
  196.                                 /* -------------------上传历史记录--------------*/
  197.                                 // 获取查询时间
  198.                                 time_t tm;
  199.                                 time(&tm);
  200.                                 struct tm *tp = localtime(&tm);
  201.                                 char timmsg[32] = {0};
  202.                                 sprintf(timmsg,"%d/%d/%d %d:%d:%d\n", tp->tm_year+1900,
  203.                                                 tp->tm_mon+1, tp->tm_mday, tp->tm_hour,
  204.                                                 tp->tm_min, tp->tm_sec);
  205.                                 char sql[128] = {0};
  206.                                 sprintf(sql,"insert into history values(%d,'%s','%s')",id,word,timmsg);
  207.                                 if(-1 == sqlite3_exec(db, sql, NULL, NULL, NULL)){
  208.                                         return -1;
  209.                                 }               
  210.                                 flag = 1;
  211.                                 break;
  212.                         }
  213.                         index+=2;
  214.                         index %= max;//防止段错误
  215.                 }
  216.         }
  217.         //循环退出时 flag 仍为 0 则未找到
  218.         if(0 == flag){
  219.                 strcpy(buf, "单词未找到\n");
  220.                 send(connfd, buf, strlen(buf), 0);
  221.                 return 0;
  222.         }
  223.         return 0;
  224. }
  225. /*------------------------------------------------------------------------*/
  226. // 成功查询的历史
  227. int history(int connfd, sqlite3 *db, int id){
  228.         char sql[128] = {0};
  229.         char buf[128] = {0};
  230.         char **result;
  231.         int row, col;
  232.         sprintf(sql, "select * from history where id=%d", id);
  233.         if(-1 == sqlite3_get_table(db, sql, &result, &row, &col, NULL)){
  234.                 sprintf(buf,"select history: %s\n", sqlite3_errmsg(db));
  235.                 send(connfd, buf, strlen(buf), 0);
  236.                 memset(buf, 0, sizeof(buf));
  237.                 return -1;
  238.         }
  239.         int max = col * row + 3;// 3 是字段数
  240.         if(3 == max){// max 为3 该用户无成功查询记录
  241.                 strcpy(buf, "NONE!");
  242.                 send(connfd, buf, strlen(buf), 0);
  243.                 return -1;
  244.         }else{
  245.                 strcpy(buf,"\n---------------成功查询历史----------------\n");
  246.                 send(connfd, buf, strlen(buf), 0);
  247.                 memset(buf, 0, sizeof(buf));
  248.                 for(int i=0; i<=row; i++){
  249.                         for(int j=0; j<col; j++){        // j 从3 开始,不传字段名
  250.                                 sprintf(buf, "%s ", result[i*col+j]);
  251.                                 send(connfd, buf, strlen(buf), 0);
  252.                                 usleep(1000);
  253.                                 memset(buf, 0, sizeof(buf));
  254.                         }
  255.                 }
  256.                 // 历史数据发送完成,发送结束信息
  257.                 strcpy(buf, "DONE!");
  258.                 send(connfd, buf, strlen(buf), 0);
  259.         }
  260.         return 0;
  261. }
  262. /*------------------------------------------------------------------------*/
  263. // 帐号操作,函数注册成功返回 0,登陆成功返回id
  264. int account(int connfd, sqlite3 *db, int mode){
  265.         int id;
  266.         char buf[128] = {0};
  267.         //注册
  268.         if(R == mode){
  269.                 int ret = user_add(connfd, db);
  270.                 if(0 == ret){
  271.                         printf("新用户注册成功!\n");
  272.                 }else if(ID_ERR){
  273.                         return ID_ERR;
  274.                 }
  275.                 return 0;//注册成功
  276.         }else if(L ==mode){
  277.                 // 登陆
  278.                 int ret = user_login(connfd, db);
  279.                 if(ID_ERR == ret){
  280.                         return ID_ERR;//id不合法
  281.                 }else if(PWD_ERR == ret){
  282.                         return PWD_ERR;//密码错误
  283.                 }else if(GET_ID_ERR == ret){
  284.                         return GET_ID_ERR;
  285.                 }else if(GET_PWD_ERR == ret){
  286.                         return GET_PWD_ERR;
  287.                 }
  288.                 return ret;
  289.         }else{
  290.                 return -1;
  291.         }
  292.         return 0;
  293. }
  294. int operation(int connfd, sqlite3 *db, int mode, int id){
  295.         if(C == mode){
  296.                 // 查询
  297.                 int ret = check(connfd, db, id);
  298.                 if(-1 == ret){
  299.                         return -1;
  300.                 }else if(Q == ret){
  301.                         return Q;
  302.                 }
  303.                 return 0;
  304.         }else if(H == mode){
  305.                 // 历史
  306.                 if(-1 == history(connfd, db, id))
  307.                         return -1;
  308.                 return 0;
  309.         }
  310. }
  311. /*------------------------------------------------------------------------*/
  312. //服务器初始化
  313. int server_init(char *ip, char* port)
  314. {
  315.         // 创建套接字
  316.         int sockfd = socket(AF_INET, SOCK_STREAM, 0);
  317.         if(-1 == sockfd){
  318.                 perror("socket");
  319.                 return -1;
  320.         }
  321.         // 绑定
  322.         struct sockaddr_in addr;
  323.         addr.sin_family = AF_INET;
  324.         addr.sin_addr.s_addr = inet_addr(ip);
  325.         addr.sin_port = htons(atoi(port));
  326.         if(-1 == bind(sockfd, (struct sockaddr *)&addr, sizeof(addr))){
  327.                 perror("connect");
  328.                 return -1;
  329.         }
  330.         // 监听
  331.         if(-1 == listen(sockfd, 10)){
  332.                 perror("listen");
  333.                 return -1;
  334.         }
  335.         printf("----------------服务启动!----------------\n");
  336.         printf("---          等待客户端连接           ---\n");
  337.         return sockfd;
  338. }
复制代码
2.5 客户端 client.c

  1. // -------------------------Client---------------------------
  2. #include "tool.h"
  3. int main(int argc, char *argv[]){
  4.         // 判断运行指令合法性
  5.         if(3 != argc){
  6.                 printf("Input like: %s IP port\n", argv[0]);
  7.                 return -1;
  8.         }
  9.         // 创建套接字
  10.         int sockfd = socket(AF_INET, SOCK_STREAM, 0);
  11.         if(-1 == sockfd){
  12.                 perror("socket");
  13.                 return -1;
  14.         }
  15.         // 连接服务器
  16.         struct sockaddr_in addr;
  17.         addr.sin_family = AF_INET;
  18.         addr.sin_addr.s_addr = inet_addr(argv[1]);
  19.         addr.sin_port = htons(atoi(argv[2]));
  20.         if(-1 == connect(sockfd, (struct sockaddr *)&addr, sizeof(addr))){
  21.                 perror("connect");
  22.                 return -1;
  23.         }
  24.         while(1){
  25.                 /*---------------------帐号操作----------------------*/
  26.                 long mode = 0;        //用户模式数
  27.                 int ret = 0;        //接收各种函数返回结果
  28.                 char ui[512] = {0};//接收UI
  29.                 char buf[128] = {0};//存储信息
  30.                 // 调用帐号UI
  31.                 UI_account();
  32.                 // 发送mode
  33.                 printf("输入您的模式选择数:\n");
  34.                 scanf("%ld", &mode);
  35.                 getchar();
  36.                 send(sockfd,(void*)&mode, sizeof(mode), 0);
  37.                 if(R == mode){
  38.                         /*-----------------------注册---------------------*/
  39.                         int id, pwd;
  40.                         printf("输入您要注册的用户id(需至少为两位数)\n");
  41.                         scanf("%d", &id);
  42.                         send(sockfd, (void*)&id, sizeof(id), 0);
  43.                         printf("输入您的密码\n");
  44.                         scanf("%d", &pwd);
  45.                         send(sockfd, (void*)&pwd, sizeof(pwd), 0);
  46.                         printf("您的 id:%d pwd: %d\n", id, pwd);
  47.                         recv(sockfd, (void*)&id, sizeof(id), 0); //接收回复
  48.                         if(0 == id){
  49.                                 printf("注册成功\n");
  50.                                 continue;
  51.                         }else if(-1 == id){
  52.                                 printf("注册失败\n");
  53.                                 continue;
  54.                         }else if(ID_ERR == id){
  55.                                 printf("用户已存在\n");
  56.                                 continue;
  57.                         }
  58.                 }else if(L == mode){
  59.                         /*-----------------------登陆---------------------*/
  60.                         int id, pwd;
  61.                         printf("输入登陆的用户id(需至少为两位数)\n");
  62.                         scanf("%d", &id);
  63.                         send(sockfd, (void*)&id, sizeof(id), 0);
  64.                         printf("输入密码\n");
  65.                         scanf("%d", &pwd);
  66.                         send(sockfd, (void*)&pwd, sizeof(pwd), 0);
  67.                         recv(sockfd, &id, sizeof(id), 0); //接收回复
  68.                         if(-1 == id){
  69.                                 printf("登陆失败\n");
  70.                                 continue;
  71.                         }else if(0 == id){
  72.                                 printf("您不能以 0 为用户名\n");
  73.                                 continue;
  74.                         }else if(GET_ID_ERR == id){
  75.                                 printf("获取id失败\n");
  76.                                 continue;
  77.                         }else if(GET_PWD_ERR == id){
  78.                                 printf("获取pwd失败\n");
  79.                                 continue;
  80.                         }else if(ID_ERR == id){
  81.                                 printf("用户id不合法\n");
  82.                                 continue;       
  83.                         }else if(PWD_ERR == id){
  84.                                 printf("密码错误\n");
  85.                                 continue;       
  86.                         }else if(9 < id){
  87.                                 /*-------------------登陆成功, 查询开始--------------------*/
  88.                                 while(1){
  89.                                         // 调用查询UI
  90.                                         UI_check();
  91.                                         // 发送mode
  92.                                         printf("输入查询模式选择数:\n");
  93.                                         scanf("%ld", &mode);
  94.                                         getchar();
  95.                                         send(sockfd, (void*)&mode, sizeof(mode), 0);
  96.                                         if(C == mode){
  97.                                                 /*----------------------查询-----------------------*/       
  98.                                                 //发送单词信息,输入的是Q则退出,当然Q也要发给服务器
  99.                                                 printf("输入您要查询的单词,输入 Q 退出\n");
  100.                                                 fgets(buf, sizeof(buf), stdin);
  101.                                                 send(sockfd, buf, strlen(buf)-1, 0);
  102.                                                 if(0 == strncmp(buf, "Q", 1)){
  103.                                                         break;
  104.                                                 }
  105.                                                 memset(buf, 0, sizeof(buf));
  106.                                                 //接受结果       
  107.                                                 char result[64] = {0};
  108.                                                 recv(sockfd, result, sizeof(result), 0);
  109.                                                 printf("%s\n", result);
  110.                                                 continue;
  111.                                         }else if(H == mode){
  112.                                                 while(1){
  113.                                                         char buf[128] = {0};
  114.                                                         int ret = recv(sockfd, buf, sizeof(buf), 0);
  115.                                                         if(-1 == ret){
  116.                                                                 perror("history recv");
  117.                                                                 break;
  118.                                                         }else if(0 == ret){
  119.                                                                 printf("客户端退出\n");
  120.                                                                 break;
  121.                                                         }
  122.                                                         // 查询成功
  123.                                                         printf("%s", buf);
  124.                                                         // 历史数据读取完成
  125.                                                         if(0 == strncmp(buf, "DONE!", 5)){
  126.                                                                 printf("\n");
  127.                                                                 break;
  128.                                                         }else if(0 == strncmp(buf, "NONE!", 5)){
  129.                                                                 //暂无历史数据
  130.                                                                 printf("\n");
  131.                                                                 break;
  132.                                                         }
  133.                                                 }
  134.                                                 continue; //返回查询界面
  135.                                         }else{
  136.                                                 puts("请输入正确的选项数");
  137.                                                 continue;
  138.                                         }
  139.                                 }
  140.                         }
  141.                 }
  142.         }
  143. }
复制代码
2.6 服务器 server.c

  1. //                -------------------------Server----------------------------
  2. #include "tool.h"
  3. /* ----------------------------main------------------------------  */
  4. int main(int argc, char *argv[])
  5. {
  6.         if(3 > argc){
  7.                 printf("参数缺失,您至少需要输入三个参数如:\n./server IP port\n");
  8.                 puts("");
  9.                 printf("第一次运行服务器,需额外输入任意数字:\n./server IP port num\n");
  10.                 return -1;
  11.         }
  12.         // 若输入了模式(第一次运行服务器,没有创建数据库)
  13.         if(4 == argc)
  14.                 database_init("data.db");
  15.         sqlite3* db;
  16.         if(0 != sqlite3_open("data.db", &db)){
  17.                 printf("data base open: %s\n", sqlite3_errmsg(db));
  18.                 return -1;
  19.         }
  20.         // 初始化服务器,得到监听套接字
  21.         int listenfd = server_init(argv[1], argv[2]);       
  22.         if(-1 == listenfd)
  23.                 return -1;
  24.         /*---------               子进程处理用户交互              ----------*/
  25.         /*-----------------一个连接一个进程--------------------*/
  26.         while(1){
  27.                 long mode = 0;// 接收用户模式
  28.                 int ret = 0;//接受一些函数的运行结果
  29.                 struct sockaddr_in client;
  30.                 socklen_t len = sizeof(client);
  31.                 int connfd = accept(listenfd, (struct sockaddr*)&client, &len);
  32.                 if(-1 == connfd){
  33.                         perror("connect");
  34.                         return -1;
  35.                 }
  36.                 puts("客户端连接成功!");
  37.                 pid_t pid = fork();
  38.                 if(-1 == pid){
  39.                         perror("fork");
  40.                         return -1;
  41.                 }else if(0 == pid){
  42.                         while(1){
  43.                                 /* --------------------- 帐号操作 ----------------------*/
  44.                                 // 用户登陆操作信息
  45.                                 ret = recv(connfd, (void*)&mode, sizeof(mode), 0);
  46.                                 if(-1 == ret){
  47.                                         perror("recv mode");
  48.                                         break;
  49.                                 }else if(0 == ret){
  50.                                         printf("客户端退出\n");
  51.                                         break;
  52.                                 }
  53.                         /* ------------------帐号操作 --------------------*/
  54.                                 // 帐号函数,登陆成功返回登陆id
  55.                                 int id = account(connfd, db, mode);
  56.                                 send(connfd, (void*)&id, sizeof(id), 0);//发送account的结果
  57.                                 if(9 < id){
  58.                                         /* ------------------ 登陆成功开始查询 --------------------*/
  59.                                         while(1){
  60.                                                 // 接收mode
  61.                                                 if(-1 == recv(connfd, (void*)&mode, sizeof(mode),0)){
  62.                                                         perror("recv mode:");
  63.                                                         exit(-1);
  64.                                                 }else if(0 == ret){
  65.                                                         printf("客户端退出\n");
  66.                                                         exit(-1);
  67.                                                 }
  68.                                                 int ret = operation(connfd, db, mode, id);
  69.                                                 if(-1 == ret){
  70.                                                         break;
  71.                                                 }else if(0 == ret){
  72.                                                         continue;
  73.                                                 }else if(Q == ret){
  74.                                                         break;
  75.                                                 }
  76.                                         }
  77.                                 }
  78.                         }
  79.                 }
  80.                 close(connfd);
  81.         }
  82.         /* -------------------------- 父进程 ------------------------------*/
  83.         wait(NULL);
  84.         close(listenfd);
  85.         sqlite3_close(db);
  86.         exit(0);
  87. }
复制代码

制作者名单

      
       文案:張嘉鑫       视图:張嘉鑫       代码:張嘉鑫       其余图片:来自网络       特殊鸣谢:李伟老师   

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

祗疼妳一个

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表