C网络编程--在线词典项目

目录

流程图

服务端 

服务端流程示意图

 服务端代码

 客户端

客户端流程示意图

 客户端代码

运行结果

服务端

客户端


流程图:

服务端 

服务端流程示意图

 服务端代码

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

enum type{
    R = 1,
    L,
    Q,
    H,
};
typedef struct{
    int type;
    char name[32];
    char data[256];
}MSG;

//声明
int 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 sockfd,MSG *msg,sqlite3 *db);
int callback(void *arg, int f_num, char **f_val, char **f_name);
int search_word(int acceptfd,MSG *msg);

int main(int argc, char const *argv[])
{
    if(argc != 2){
        printf("plase input:%s <port>\n",argv[0]);
        return -1;
    }

    sqlite3 *db = NULL;  
    if(sqlite3_open("./student.db",&db) != SQLITE_OK){
        //student 是数据库  数据库里有很多的表
        fprintf(stderr,"sqlite3_open err:%s\n",sqlite3_errmsg(db));
        return -1;
    }

    //创建用户表,注册登录时候使用
    char *errmsg;
    if(sqlite3_exec(db,"create table users(name char,password char)",NULL,NULL,&errmsg)!=SQLITE_OK){
        fprintf(stderr,"create table err:%s\n",errmsg);
    }

    //创建历史记录表,查询历史记录
    if(sqlite3_exec(db,"create table record(name char,word char,time char);",NULL,NULL,&errmsg)!=SQLITE_OK){
        fprintf(stderr,"create table err:%s\n",errmsg);
    }

    //创建套接字
    int sockfd;
    sockfd = socket(AF_INET,SOCK_STREAM,0);
    if(sockfd < 0){
        perror("socket err\n");
        return -1;
    }
    printf("sockfd:%d",sockfd);

    struct sockaddr_in serveraddr,clientaddr;
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(atoi(argv[1]));
    serveraddr.sin_addr.s_addr = inet_addr("0.0.0.0");

    socklen_t len = sizeof(clientaddr);

    //绑定
    if(bind(sockfd,(struct sockaddr*)&serveraddr,sizeof(serveraddr))<0){
        perror("bind err\n");
        return -1;
    }
    printf("bind ok\n");

    if(listen(sockfd,5)<0){
        perror("listen err\n");
        return -1;
    }
    printf("listen ok\n");

    //处理僵尸进程
    signal(SIGCHLD,SIG_IGN);
    
    //循环接受阻塞
    while(1){
        int acceptfd;
        acceptfd=accept(sockfd,(struct sockaddr*)&clientaddr,&len);
        if(acceptfd<0){
            perror("accept err\n");
            return -1;
        }
        printf("acceptfd:%d",acceptfd);
        printf("ip:%s port:%d",inet_ntoa(clientaddr.sin_addr),ntohs(clientaddr.sin_port));
        
        pid_t pid;
        pid = fork();
        if(pid < 0){
            perror("fork err\n");
            return -1;
        }else if(pid == 0){
            MSG msg;
            while(1){
                int recvbyte;
                recvbyte = recv(acceptfd,&msg,sizeof(MSG),0);
                if(recvbyte<0){
                    perror("recv err\n");
                    return -1;
                }else if(recvbyte == 0){
                    printf("client exit\n");
                    kill(pid,SIGKILL);
                    break;
                }else{
                    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;
                    }
                }
            }

        }else{
            printf("login!\n");
            close(acceptfd);
        }
    }

    close(sockfd);
    return 0;
}

int do_register(int acceptfd,MSG *msg,sqlite3 *db){
    char *errmsg;
    char sql[128];    //结构体里包括type 。。 name  data(passworld和word)
    sprintf(sql,"insert into users values('%s','%s');",msg->name,msg->data);
    if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK){
       fprintf(stderr,"insert err:%s\n",errmsg);
       sprintf(msg->data,"user %s already exit",msg->name);
       return -1;
    }else{
        strcpy(msg->data,"ok");
    }
    
    //返回应答
    if(send(acceptfd,msg,sizeof(MSG),0)<0){
        perror("send err\n");
        return -1;
    } 
    return 0;
}   

//登录
int do_login(int acceptfd,MSG *msg,sqlite3 *db){
    char **res=NULL;
    int row,col;
    char *errmsg;
    char sql[128];
    sprintf(sql,"select * from users where name = '%s' and password = '%s';",msg->name,msg->data);
    if(sqlite3_get_table(db,sql,&res,&row,&col,&errmsg)!=0){
        fprintf(stderr,"select err:%s\n",errmsg);
        return -1;
    }if(row == 0){
        strcpy(msg->data,"name or password err\n");
    }else{
        strcpy(msg->data,"ok");
    }
    if(send(acceptfd,msg,sizeof(MSG),0)<0){
        perror("send err\n");
        return -1;
    } 
    return 0;
}


//查询
int do_query(int acceptfd,MSG *msg,sqlite3 *db){
    char date[128];
    char sql[128];
    char *errmsg;
    char word[128];
    strcpy(word, msg->data);
    int find = search_word(acceptfd, msg);
    if (find == 1){
        //获取时间
        time_t t1;
        struct tm *t;
        t1 = time(&t1);
        t = localtime(&t1);
        sprintf(date, "%d-%d-%d %d:%d:%d", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
        //将查询记录插入到记录表中
        sprintf(sql, "insert into record values('%s','%s','%s');", msg->name, word, date);
        if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != 0)
        {
            fprintf(stderr, "insert err:%s\n", errmsg);
            return -1;
        }
    }else{  //没找到对应单词
            strcpy(msg->data, "not found");
            if (send(acceptfd, msg, sizeof(MSG), 0) < 0)
            {
                perror("send err");
                return -1;
            }
        }
    return 0;
}
//历史记录
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, callback, &acceptfd, &errmsg) != 0){
        fprintf(stderr, "insert err:%s\n", errmsg);
    }
    msg->data[0] = '\0';
    if (send(acceptfd, msg, sizeof(MSG), 0) < 0)
    {
        perror("send err");
        return -1;
    }
    return 0;
}

//回调
int callback(void *arg, int f_num, char **f_val, char **f_name){
    int acceptfd;
    MSG msg;
    acceptfd = *(int *)arg;
    sprintf(msg.data, "%s : %s", f_val[1], f_val[2]);
    if (send(acceptfd, &msg, sizeof(MSG), 0) < 0){
        perror("send err");
        return -1;
    }
    return 0;
}

//查找单词
int search_word(int acceptfd,MSG *msg){
    FILE *fp = fopen("./dict.txt", "r");
    if (fp == NULL){
        perror("fopen err");
        return -1;
    }
    int len = strlen(msg->data);
    char word[300];
    while (fgets(word, 300, fp))
    {
        if (word[strlen(word) - 1] == '\n'){
            word[strlen(word) - 1] = '\0';
        }   
        //fgets \n 结束
        int ret = strncmp(msg->data, word, len);  //比较msg->data 和 word  比较长度len
        if (ret == 0 && word[len] == ' ')
        {
            char *p = word + len;
            while (*p == ' '){
                p++;
            } 
            strcpy(msg->data, p);
        }
    }
    if (send(acceptfd, msg, sizeof(MSG), 0) < 0)
    {
        perror("send err");
        return -1;
    }
    fclose(fp);
    return 1;
}

    

    

 客户端

客户端流程示意图

 客户端代码

#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> 
#include <unistd.h> 
#include <arpa/inet.h>
#include <stdlib.h>
#include <sqlite3.h>
#include <string.h>
enum type{
    R=1, //注册
    L, //登录
    Q, //查询
    H,//历史
};

typedef struct{
    int type;
    char name[32];
    char data[256]; //passworld or world;
}MSG;

MSG msg;

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

int main(int argc, char const *argv[])
{
   
    if (argc != 3){
        printf("please input:%s <ip> <port>\n", argv[0]);
        return -1;
    }
    int sockfd,acceptfd;
    sockfd = socket(AF_INET,SOCK_STREAM,0);
    if(sockfd < 0){
        perror("socket err\n");
        return -1;
    }
    printf("sockfd:%d\n",sockfd);

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

    if(connect(sockfd,(struct sockaddr *)&serveraddr,sizeof(serveraddr))<0){
        perror("connect err");
        return -1;
    }
    printf("connect ok\n");
    
    while(1){
        MSG msg;
        int n;
        printf("*****************************************************\n");
        printf("*********** 1: register 2:login 3: quit *************\n");
        printf("*****************************************************\n");
        printf("****************** plase choose : *******************\n");
        scanf("%d",&n);
        switch (n){
        case 1 :
               do_register(sockfd,&msg);
               break;
        case 2 :
               if(do_login(sockfd,&msg)==1){
                   goto next;
                } 
                break;
        case 3 :
               close(sockfd);
               exit(0);
        }
    }

next:
    while(1){
        MSG msg;
        int m;
        printf("***********************************************\n");
        printf("**1:query_world    2:history_recond   3:quit **\n");
        printf("***********************************************\n");
        printf("*****************  plase choose  **************\n");
        scanf("%d",&m);
        switch (m){
        case 1 :
            do_query(sockfd,&msg);
            break;
        case 2 :
            do_history(sockfd,&msg);
            break;
        case 3 :
            close(sockfd);
            exit(0);
        }
    }
 return 0;
}

int do_register(int sockfd,MSG *msg){
    msg->type = R;
    printf("请输入用户名: ");
    scanf("%s",msg->name);
    printf("请输入密码:");
    scanf("%s",msg->data);

    if(send(sockfd,msg,sizeof(MSG),0)<0){
        perror("send err\n");
        return -1;
    }

    if(recv(sockfd,msg,sizeof(MSG),0)<0){
        perror("recv err\n");
        return -1;
    }
    printf("%s\n",msg->data);
    return 0;

   
}
//登录
int do_login(int sockfd,MSG *msg){
    msg->type = L; 
    printf("请输入用户名: \n");
    scanf("%s",msg->name);
    printf("请输入密码:\n");
    scanf("%s",msg->data);

    if(send(sockfd,msg,sizeof(MSG),0)<0){
        perror("send err\n");
        return -1;
    }

    if(recv(sockfd,msg,sizeof(MSG),0)<0){
        perror("recv err\n");
        return -1;
    }

    if(strncmp(msg->data,"ok",2)==0){
        printf("用户登录成功!%s\n",msg->data);
        return 1;
    }
}

//查询
int do_query(int sockfd,MSG *msg){
    msg->type = Q;
    while(1){
        printf("输入你想查的单词,#退出,请输入:");
        scanf("%s",msg->data);
        if(strcmp(msg->data,"#")==0){
            break;
        }     //想要查询的目的完成
    
        if(send(sockfd,msg,sizeof(MSG),0)<0){
        perror("send err\n");
        return -1;
        }

        if(recv(sockfd,msg,sizeof(MSG),0)<0){
        perror("recv err\n");
        return -1;
        }
        printf("**********************************\n");
        printf("你想查询的单词结果:%s\n",msg->data);
        printf("**********************************\n");
    }
    return 0;
}

int do_history(int sockfd,MSG *msg){
    msg->type = H;
    if(send(sockfd,msg,sizeof(MSG),0)<0){
        perror("send err");
        return -1;
    }
    while(1){
        if(recv(sockfd,msg,sizeof(MSG),0)<0){
            perror("send err");
            return -1;
        }
        if(msg->data[0]=='\0'){
            break;
        }
        printf("历史浏览记录:%s\n",msg->data);
    }
    return 0;
}

运行结果

服务端

客户端

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值