1.头文件

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>          /* See NOTES */
#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>

2.宏定义

#define  R  1   // user - register
#define  L  2   // user - login
#define  Q  3   // user - query
#define  H  4   // user - history
#define N 128
//char *errmsg=NULL;
typedef struct{char type;char name[N];char data[512];
}MSG;//规定传输的格式

3.服务器主程序

服务器创建一个套接字即所谓的sockfd用于监听,绑定,以及创建用于通信的套接字——调用accept函数,当一个进程连接上就会返回一个通信套接字,另一个进程连上会返回一个看似一样但是不一样的通讯套接字,就像是sql语言中NULL永远会不同于其他字符,哪怕是另一个NULL依然有效。

我们将父进程的通用套接字关闭,只用于监听是否有客户端连接,子进程只用于接收,避免了同一时间只能连接一个用户的囧境。

int main(int argc, const char *argv[])
{MSG msg;sqlite3 *db;int sockfd;char *errmsg=NULL;if(0!=sqlite3_open("test.db",&db)){fprintf(stderr,"sqlite_open failed:%s",sqlite3_errmsg(db));return -1;}printf("sqlite_open ok;\n");sqlite3_exec(db,"create table if not exits usr (name char,password char);",NULL,NULL,&errmsg);
sqlite3_exec(db,"create table if not exits record_test(name char,data char,word char);",NULL,NULL,&errmsg)!=0);printf("the table create ok\n");sockfd=socket(AF_INET,SOCK_STREAM,0);struct sockaddr_in serveraddr;struct sockaddr_in clientaddr;
//填充结构体serveraddr.sin_family=AF_INET;serveraddr.sin_port=htons(8898);serveraddr.sin_addr.s_addr=inet_addr("127.0.0.1");socklen_t addrlen=sizeof(serveraddr);socklen_t clientlen=sizeof(clientaddr);
//绑定if(bind(sockfd,(struct sockaddr *)&serveraddr,addrlen)<0){perror("bind");exit(1);}printf("bind\n");
//监听if(0> listen(sockfd,5)){perror("listen");exit(1);}printf("listen\n");pid_t pid;char buf[N]={0};int acceptfd;
// 处理僵尸进程signal(SIGCHLD,handler);while(1){acceptfd=accept(sockfd,(struct sockaddr *)&clientaddr,&clientlen);pid=fork();
//fork函数创建进程
//1.创建失败 2.子进程 3.父进程:父进程用于监听和连接,子进程用于通信if(pid<0){perror("failed to fork");exit(1);}else if(pid==0){ close(sockfd);do_client(acceptfd,db);}elseclose(acceptfd);} sqlite3_close(db);return 0;
}

4.客户端信号的处理

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': process_register(acceptfd,&msg,db);break;case 'L': process_login(acceptfd,&msg,db);break;case 'Q': process_query(acceptfd,&msg,db);break;case 'H': process_history(acceptfd,&msg,db);break;default:printf("invalid data msg.\n");}}printf("client exit\n");close(acceptfd);exit(0);}

5.客户端的主函数(字符界面)

int main(int argc, const char *argv[])
{int sockfd;MSG msg;MSG *msgp = NULL;sockfd=socket(AF_INET,SOCK_STREAM,0);if(sockfd<0){perror("sockfd.");exit(1);}struct sockaddr_in serveraddr;bzero(&serveraddr,sizeof(serveraddr));//清零 serveraddr.sin_family=AF_INET;serveraddr.sin_port=htons(8898);serveraddr.sin_addr.s_addr=inet_addr("127.0.0.1");socklen_t addrlen=sizeof(serveraddr);connect(sockfd,(struct sockaddr *)&serveraddr,addrlen);char buf[N]={0};int n;while(1){printf("***********************\n");printf("******1:register****\n");printf("******2:login*******\n");printf("******3.quit********\n");printf("***********************\n");printf("please choose\n");fgets(buf,sizeof(buf),stdin);printf("%s\n",buf);switch(buf[0]){case '1':do_register(sockfd,&msg);break;case '2':if(do_login(sockfd,&msg)==1){goto next;}break;case '3':close(sockfd);exit(0);break;default:printf("input again\n");continue;}}while(1){
next:printf("************************************\n");printf("**1:querry_word**2:history**3:quit**\n");printf("************************************\n");printf("please choose:\n");fgets(buf,sizeof(buf),stdin);switch(buf[0]){case '1':do_query(sockfd,&msg);break;case '2':do_history(sockfd,&msg);break;case '3':close(sockfd);exit(0);default:printf("invalid data\n");}}return 0;
}

6.注册功能实现

(1)客户端

int do_register(int sockfd,MSG *msg)
{ msg->type='R';printf("your usrname:\n");scanf("%s",msg->name);printf("your password:\n");scanf("%s",msg->data);printf("%c,%s,%s\n",msg->type,msg->name,msg->data);pid_t pid;if(send(sockfd,msg,512,0)<0){printf("failed to send\n");return 1;}if(recv(sockfd,msg,sizeof(MSG),0)<0){printf("failed to recv\n");return 1;}printf("%s\n",msg->data);return 0;
}

(2)服务器端

void process_register(int acceptfd,MSG *msg, sqlite3 * db)
{char sql[64]={0};char *errmsg=NULL;sprintf(sql,"insert into usr values('%s','%s');",msg->name,msg->data);printf("%s\n",sql);if(0!= sqlite3_exec(db,sql,NULL,NULL,&errmsg)){printf("%s\n",errmsg);strcpy(msg->data,"usrname already exit.");}else{printf("client register ok.\n");strcpy(msg->data,"OK!");}if(send(acceptfd,msg,sizeof(MSG),0)<0){perror("failed to send");return;}return;}

7.登录功能的实现

(1)客户端

int do_login(int sockfd,MSG *msg)
{pid_t pid;msg->type='L';printf("input your name\n");scanf("%s",msg->name);getchar();printf("input your password\n");scanf("%s",msg->data);getchar();send(sockfd,msg,sizeof(MSG),0);printf("%s\n",msg->data);recv(sockfd,msg,sizeof(MSG),0);printf("%s\n",msg->data);if(strncmp(msg->data,"OK",3)==0){printf("Login ok\n");return 1;}else {printf("%s",msg->data);return 0;}}

(2)服务器端

int  process_login(int acceptfd,MSG *msg,sqlite3 *db)
{   char **resultp=NULL;int nrow,ncolumn;char *errmsg=NULL;char sql[512]={0};printf("a2\n");sprintf(sql,"select * from usr where name = '%s' and password = '%s';",msg->name,msg->data);if(0!= sqlite3_get_table(db,sql,&resultp,&nrow,&ncolumn,&errmsg)){printf("%s\n",errmsg);return -1;}else{printf("get_table ok!\n");}if(nrow==0){strcpy(msg->data,"usr/pwd wrony");send(acceptfd,msg,sizeof(MSG),0);   }else if(nrow==1){strcpy(msg->data,"OK");send(acceptfd,msg,sizeof(MSG),0);return 1;}return 0;
}

8.查询功能

(1)客户端

void do_query(int sockfd,MSG *msg)
{msg->type='Q';puts("-----------------------------");while(1){printf("input word:");fgets(msg->data,sizeof(msg->data),stdin);msg->data[strlen(msg->data)-1]='\0';if(strncmp(msg->data,"#",1)==0)break;if(send(sockfd,msg,sizeof(MSG),0)<0){printf("failed to send\n");return ;}printf("%c,%s",msg->type,msg->data);printf("send ok.\n");if(recv(sockfd,msg,1024,0)<0){printf("failed to recv\n");return ;}printf("%s\n",msg->data);}return ;
}

(2)服务器端

int do_searchword(int acceptfd,MSG *msg,char word[])
{FILE *fp=NULL;char buffer[1024]={0};int len;if((fp=fopen("./dict.txt","r"))==NULL){perror("fail to fopen.\n");strcpy(msg->data, "Failed to open dict.txt");send(acceptfd,(MSG*)&msg, sizeof(MSG), 0);return 1;}len=strlen(word);printf("%s,len=%d\n",word,len);int result;char *p=NULL;while(fgets(buffer,1024,fp)!=NULL){   result=strncmp(buffer,word,len);if(result<0){continue;}if(result>0||((result == 0)&&(buffer[len]!=' ')))break;p=buffer + len;while(*p== ' '){p++;}strcpy(msg->data,p);printf("%s\n",msg->data);fclose(fp);return 1;}fclose(fp);return 0;
}
int get_time(char *data)
{struct tm *tm_p=NULL;time_t dtime;time(&dtime);tm_p=localtime(&dtime);sprintf(data,"%d-%d-%d %d:%d:%d\n",tm_p->tm_year + 1900,tm_p->tm_mon + 1,\tm_p->tm_mday,tm_p->tm_hour,tm_p->tm_min,tm_p->tm_sec);printf("get data:%s\n",data);return 0;
}
void process_query(int acceptfd,MSG *msg,sqlite3 *db)
{int found;char word[64]={0};char data[128]={0};char sql[128]={0};char *errmsg =NULL;strcpy(word,msg->data);found=do_searchword(acceptfd,msg,word);if(found==1){get_time(data);sprintf(sql,"insert into record_test values('%s','%s','%s')",msg->name,data,word);if(0!=sqlite3_exec(db,sql,NULL,NULL,&errmsg)){printf("%s\n",errmsg);return ;}else{printf("insert record done.\n");}}else{strcpy(msg->data,"NO found");printf("aaaa\n");}if(send(acceptfd,msg,sizeof(MSG),0)<0){perror("failed to send");}
}

9 历史查询

(1)客户端

void 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);}}

(2)服务器端

int history_callback(void* arg,int f_num,char** f_value,char** f_name)
{int accptfd;MSG msg;accptfd=*((int *)arg);sprintf(msg.data,"%s ,%s",f_value[1],f_value[2]);send(accptfd,&msg,sizeof(msg),0);return 0;
}void process_history(int acceptfd,MSG *msg,sqlite3 * db)
{char sql[128]={0};char *errmsg=NULL;sprintf(sql,"select * from record where name ='%s';",msg->name);if(0!=sqlite3_exec(db,sql,history_callback,(void *)&acceptfd,&errmsg)){printf("%s\n",errmsg);}else{printf("record done.\n");}msg->data[0]='\0';send(acceptfd,msg,sizeof(MSG),0);
}

10 僵尸进程处理函数

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

本文纯属个人笔记,如有错误,还望不吝指点,如有雷同,你来打我呀

网络编程实战之在线电子词典相关推荐

  1. 北京迅为IMX6ULL开发板 DHT11网络编程实战练习

    转自:[北京迅为i.mx6ull终结者开发板使用手册]第六十三章 QT 实战项目 硬件平台:IMX6ULL开发板   63.1 DHT11&网络编程实战练习 本项目为阶段性练习,内容简洁实用, ...

  2. 迅为-i.MX6ULL开发板-QT实战项目DHT11网络编程实战练习(一)

    迅为-i.MX6ULL开发板-QT实战项目DHT11&网络编程实战练习(一) 发布时间:2021-7-2 09:49    发布者:落风 |编辑 文章目录1 项目前准备2 软件流程图3 Lin ...

  3. 陈硕《网络编程实战》01 网络编程概要

    陈硕<网络编程实战> 01 网络编程概要 站在巨人的肩膀之上. 按照录像整理,部分专有名词不太肯定,版权归陈硕大神. 大家好,我是陈硕,受邀讲授一门有关网络编程的在线课程,这门课程的名称是 ...

  4. 基于Winsock API的VC网络编程实战

    基于Winsock API的VC网络编程实战 随着计算机信息技术的飞速发展,互联网与人类社会的工作.生活越来越紧密相关,它已经成为人类获取.交流信息的重要途径和手段.所以当前对于开发人员来说,网络编程 ...

  5. NIO网络编程实战之简单多人聊天室

    NIO网络编程实战 利用NIO编程知识,实现多人聊天室. 1. NIO编程实现步骤 第一步:创建Selector 第二步:创建ServerSocketChannel,并绑定监听端口 第三步:将Chan ...

  6. Java并发编程实战_阿里P9整理分享的亿级流量Java高并发与网络编程实战PDF

    前言 为了帮助初级开发者快速掌握高并发.网络编程.微服务.海量数据的处理这些实用技术,本文以"理论+范例"的形式对各个知识点进行了详细的讲解,力争让读者在实践中快速掌握相关知识. ...

  7. Netty网络编程实战2,使用Netty开发聊天室功能

    目录 一.服务端 1.主程序类 2.自定义初始化器 3.自定义处理器 二.客户端 1.主程序类 2.自定义初始化器 3.自定义处理器 三.启动服务端.客户端 1.服务端:你好,我是服务端,哪吒编程 2 ...

  8. Qt网络编程实战之HTTP服务器-安晓辉-专题视频课程

    Qt网络编程实战之HTTP服务器-30196人已学习 课程介绍         设计了一个实用的HTTP服务器,基于Qt的网络框架实现.先详细介绍Qt的网络.IO.线程..自定义事件.配置文件等类库的 ...

  9. 【基于TCP 在线电子词典】

    基于TCP 在线电子词典 项目功能 流程图 客户端 服务器端 功能实现 服务器 客户端 功能演示 注册功能 登录功能 查询单词功能 查询记录 注销登录(返回上级) 不允许重复登录 Ctrl + C注销 ...

  10. java网络编程技术学习笔记(b站【狂神说Java】网络编程实战讲解)

    b站视频链接:[狂神说Java]网络编程实战讲解 文章目录 网络编程 1.1.概述 1.2.网络通信的要素 1.3.IP 1.4.端口 1.5.通信协议 1.6.TCP 文件发送 1.7.UDP 1. ...

最新文章

  1. Node Sass does not yet support your current environment: Windows 64-bit然如何解决,cnpm此问题解决方法
  2. JSESSIONID的简单说明
  3. org.apache.hadoop.hdfs.server.namenode.SafeModeException
  4. vue 页面切换动画_Flutter Hero动画让你的APP页面切换充满动效 不一样的体验 不一样的细节处理...
  5. 【架构师】【数据库基础】【笔记 01】快速了解数据库系统的重要概念02
  6. graphpad画生存曲线怎么样去掉删失点_GraphPad作生存曲线数据点超出轴限制
  7. 吴恩达-coursera-机器学习-week8
  8. python解释器中help的用法
  9. ceph 代码分析 读_Ceph代码分析
  10. Java短信确认机制_JAVA 消息确认机制之 ACK 模式
  11. 淘宝API_item_cat_get - 获得淘宝商品类目
  12. InstallShield自定义对话框浅谈(转)
  13. 协同过滤算法(基于用户)
  14. rsi红绿多空波段副图指标 rsi指标公式趋势,兼容通达信公式
  15. 东北大学计算机学硕复试分数线,东北大学2019年考研复试分数线已公布
  16. Win7 系统美化知识
  17. 12对胸椎对应体表标志_人体体表标志【图文】
  18. 金蝶EAS BOS上如何打补丁
  19. 帆软报表FineReport出现数据在一页呈现,并且多行挤在一起的情况
  20. 3D建模行业真的那么糟糕吗?

热门文章

  1. vbb bbcode
  2. 计算机二级java难不_计算机二级java含金量如何 对就业有帮助吗
  3. java蓝牙开发_Android蓝牙开发全面总结
  4. IEC61850 总结
  5. 数字电子技术反应时间测试电路(纯电路实现)
  6. java替换的程序_Java文本文件批量替换小程序的方法
  7. 中小学创客教室建设,教育创客空间整体解决方案
  8. 事记:关于远控软件导致win10屏幕亮度无法调节的解决方案
  9. 1.4_2 Axure RP 9 for mac 高保真原型图 - 案例1 【基础】模仿微信页面
  10. 免费录屏软件有哪些?分享4个专业录屏软件