基于tcp协议的电子辞典项目

功能:基于Linux操作系统,网络编程和数据库实现在线词典

(如果小编有哪个地方需要改进的,欢迎在评论区探讨哦~)


服务器端流程图(如下图所示),根据流程图编写对应的函数会相对来说简单很多,会帮助你理清思路:

 

客户端流程图(如下图所示):

 

.h文件如下:

#ifndef __DICT_H__
#define __DICT_H__
#include <stdio.h>
#include <sqlite3.h>
#include <sys/types.h>         
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
#include <time.h>

typedef struct{
    int type;
    char name[32];
    char data[500];
}MSG;

void do_register(int sockfd,MSG *msg);
int do_login(int sockfd,MSG *msg);
void do_query(int sockfd,MSG *msg);
void do_history(int sockfd, MSG *msg);
void server_register(int acceptfd,MSG *msg,sqlite3 *db);
void server_login(int acceptfd,MSG *msg,sqlite3 *db);
int server_search(int acceptfd,MSG *msg);
void server_query(int acceptfd,MSG *msg,sqlite3 *db);
void handler(int sig);
int history_callback(void *arg, int f_num, char **f_value, char **f_name);
void server_history(int acceptfd,MSG *msg,sqlite3 *db);


#endif

 函数接口:

#include "dict.h"

//注册
void do_register(int sockfd, MSG *msg)
{
    msg->type = 'R';
    printf("input name:");
    scanf("%s", msg->name);
    printf("input password:");
    scanf("%s", msg->data);
    if (send(sockfd, msg, sizeof(MSG), 0) < 0)
    {
        perror("send error");
        return;
    }
    if (recv(sockfd, msg, sizeof(MSG), 0) < 0)
    {
        perror("recv error");
        return;
    }
    printf("%s\n", msg->data);
}
//登录
int do_login(int sockfd, MSG *msg)
{
    msg->type = 'L';
    printf("input name:");
    scanf("%s", msg->name);
    printf("input password:");
    scanf("%s", msg->data);
    if (send(sockfd, msg, sizeof(MSG), 0) < 0)
    {
        perror("send error");
        return -1;
    }
    if (recv(sockfd, msg, sizeof(MSG), 0) < 0)
    {
        perror("recv error");
        return -1;
    }
    if (strncmp(msg->data, "ok", 2) == 0)
    {
        printf("login success\n");
        return 1;
    }
    printf("%s\n", msg->data);
    return 0;
}
//查询
void do_query(int sockfd, MSG *msg)
{
    msg->type = 'Q';
   
    while (1)
    {
        printf("input word(# to quit) :");
        scanf("%s", msg->data);
        if (strncmp(msg->data, "#", 1) == 0)
        {
            break;
        }
        else
        {
            if (send(sockfd, msg, sizeof(MSG), 0) < 0)
            {
                perror("send error");
                return;
            }
            if (recv(sockfd, msg, sizeof(MSG), 0) < 0)
            {
                perror("recv error");
                return;
            }
        }
        printf("%s\n",msg->data);
       
    }
}
//历史记录
void do_history(int sockfd, MSG *msg)
{
    msg->type = 'H';
    if (send(sockfd, msg, sizeof(MSG), 0) < 0)
    {
        perror("send error");
        return;
    }
    while (1)
    {
        if (recv(sockfd, msg, sizeof(MSG), 0) < 0)
        {
            perror("recv error");
            return;
        }
        if (strncmp(msg->data, "over", 4) == 0)
        {
            break;
        }
       printf("%s\n", msg->data);
        
    }
}
//回收进程资源
void handler(int sig)
{
    wait(NULL);
}
//服务器注册
void server_register(int acceptfd, MSG *msg, sqlite3 *db)
{
    char *errmsg = NULL;
    char sql[512];
    sprintf(sql, "insert into usr values('%s','%s')", msg->name, msg->data);
    if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != 0)
    {
        fprintf(stderr, "seqlite3_exec error %s\n", errmsg);
        strcpy(msg->data, "用户已存在");
    }
    else
    {
        strcpy(msg->data, "register ok");
    }
    if (send(acceptfd, msg, sizeof(MSG), 0) < 0)
    {
        perror("send error");
        return;
    }
}
//服务器登录
void server_login(int acceptfd, MSG *msg, sqlite3 *db)
{
    char *errmsg = NULL;
    char sql[512];
    int h, l;
    char **result;
    sprintf(sql, "select * from usr where name ='%s' and pwd ='%s' ", msg->name, msg->data);
    if (sqlite3_get_table(db, sql, &result, &h, &l, &errmsg) != 0)
    {
        fprintf(stderr, "seqlite3_get_table error %s\n", errmsg);
    }
    if (h == 0)
    {
        strcpy(msg->data, "用户名或密码错误,请重新登录");
    }
    else
    {
        strcpy(msg->data, "ok");
    }
    if (send(acceptfd, msg, sizeof(MSG), 0) < 0)
    {
        perror("send error");
        return;
    }
}
//根据传过来的数据在文件里进行查找
int server_search(int acceptfd, MSG *msg)
{
    char buf[500];
    char *p = NULL;
    char word[256];
    int s, len;
    len = strlen(msg->data);
    strcpy(word, msg->data);

    FILE *fp = fopen("dict.txt", "r");
    if (fp == NULL)
    {
        perror("fopen error");
        strcpy(msg->data, "can't open file");
        if (send(acceptfd, msg, sizeof(MSG), 0) < 0)
        {
            perror("send error");
            return -1;
        }
    }
    while (fgets(buf, 500, fp) != NULL)
    {
        if (strncmp(buf, word, len) == 0 && buf[len] == ' ')
        {
            p = buf + len;
            while (*p == ' ')
                p++;
            strcpy(msg->data, p);
            printf("%s\n",msg->data);
            if (send(acceptfd, msg, sizeof(MSG), 0) < 0)
            {
                perror("send error");
                return -1;
            }
            return 1;
        }
    }
    return 0;
}
//服务器查询操作
void server_query(int acceptfd, MSG *msg, sqlite3 *db)
{
    char *errmsg = NULL;
    char sql[512];
    char ltime[256];
    int flag;
    char word[256];
    strcpy(word, msg->data);
    flag = server_search(acceptfd, msg);
    if (flag == 0)
    {
        strcpy(msg->data, "the word isn't exit\n");
        if (send(acceptfd, msg, sizeof(MSG), 0) < 0)
        {
            perror("send error");
            return;
        }
    }
    if (flag == 1)
    {
        time_t seconds;
        struct tm *NowTime;
        time(&seconds);
        NowTime = localtime(&seconds);
        sprintf(ltime, "%d-%d-%d %d:%d:%d", 1900 + NowTime->tm_year, 1 + NowTime->tm_mon, NowTime->tm_mday, NowTime->tm_hour, NowTime->tm_min, NowTime->tm_sec);
        sprintf(sql, "insert into record values('%s','%s','%s')", msg->name, ltime, word);
        if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != 0)
        {
            fprintf(stderr, "seqlite3_exec error %s\n", errmsg);
        }
    }
}
//调用callback函数
int history_callback(void *arg, int f_num, char **f_value, char **f_name)
{
    int acceptfd = *(int *)arg;
    MSG msg;
    sprintf(msg.data, "%s: %s" , f_value[1], f_value[2]);
    if (send(acceptfd, &msg, sizeof(MSG), 0) < 0)
    {
        perror("send error");
        return -1;
    }
    return 0;
}
//查看对应用户的搜索记录
void server_history(int acceptfd, MSG *msg, sqlite3 *db)
{
    char *errmsg = NULL;
    char sql[256] = {0};
    sprintf(sql, "select * from record where name = '%s'", msg->name);
    if (sqlite3_exec(db, sql, history_callback, (void *)&acceptfd, &errmsg) != 0)
    {
        fprintf(stderr, "seqlite3_exec error %s\n", errmsg);
    }
    strcpy(msg->data, "over");
    if (send(acceptfd, msg, sizeof(MSG), 0) < 0)
    {
        perror("send error");
        return;
    }
}

server(循环等待接受并处理客户端的请求   注册、登录、查询、退出):

#include"dict.h"

int main(int argc, char const *argv[])
{
    int sockfd,acceptfd;
    sqlite3 *db;
    char *errmsg = NULL;
    if(sqlite3_open("./dict.db",&db)!=0){
        fprintf(stderr,"sqlite3_open error %s\n",sqlite3_errmsg(db));
        return -1;
    }
     if (sqlite3_exec(db, "create table usr(name char primary key, pwd char);", NULL, NULL, &errmsg) != 0)
    {
        fprintf(stderr, "seqlite3_exec error %s\n", errmsg);
    }
     if (sqlite3_exec(db, "create table record(name char,time char,word char);", NULL, NULL, &errmsg) != 0)
    {
        fprintf(stderr, "seqlite3_exec error %s\n", errmsg);
    }
    sockfd=socket(AF_INET,SOCK_STREAM,0);
    if(sockfd<0){
        perror("socket error");
        return -1;
    }
    struct sockaddr_in sockaddr,caddr;
    sockaddr.sin_family=AF_INET;
    sockaddr.sin_port=htons(atoi(argv[1]));
    sockaddr.sin_addr.s_addr=inet_addr("0.0.0.0");
    socklen_t len=sizeof(caddr);
    if(bind(sockfd,(struct sockaddr *)&sockaddr,sizeof(sockaddr))<0){
        perror("bind error");
        return -1;
    }
    if(listen(sockfd,5)<0){
        perror("listen error");
        return -1;
    }
    signal(SIGCHLD,handler);
   while(1){
       acceptfd=accept(sockfd,(struct sockaddr *)&caddr,&len);
       if(acceptfd<0){
           perror("accept error");
           return -1;
       }
       printf("port: %d ip:%s \n",ntohs(caddr.sin_port),inet_ntoa(caddr.sin_addr));
       pid_t pid;
       pid=fork();
       MSG msg;
       if(pid<0){
           perror("fork error");
           return -1;
       }
       else if(pid==0){
           close(sockfd);
           while(1){
               if(recv(acceptfd,&msg,sizeof(msg),0)<0){
                   perror("recv error");
                   return -1;
               }
               switch(msg.type){
               case'R':server_register(acceptfd,&msg,db);break;
               case'L':server_login(acceptfd,&msg,db);break;
               case'Q':server_query(acceptfd,&msg,db);break;
               case'H':server_history(acceptfd,&msg,db);break;    
               }
       }
   }close(acceptfd);
   }
   close(sockfd);
    return 0;
}

client (获取用户数据并发送请求   注册、登录、查询、退出):

#include"dict.h"

int main(int argc, char const *argv[])
{
    int sockfd;
    sockfd=socket(AF_INET,SOCK_STREAM,0);
    if(sockfd<0){
        perror("socket error");
        return -1;
    }
    struct sockaddr_in sockaddr;
    sockaddr.sin_family=AF_INET;
    sockaddr.sin_port=htons(atoi(argv[1]));
    sockaddr.sin_addr.s_addr=inet_addr(argv[2]);
    if(connect(sockfd,(struct sockaddr *)&sockaddr,sizeof(sockaddr))<0){
        perror("connect error");
        return -1;
    }
    MSG msg;
    int n;
    while(1){
        printf("***********************************\n");
        printf("* 1: register  2: login  3: quit *\n");
        printf("***********************************\n");
        printf("please chose:");
        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);break;
        }
    }
next:
while(1){
        printf("**********************************************\n");
        printf("* 1: query_word  2: history_record  3: quit *\n");
        printf("**********************************************\n");
        printf("please chose:");
        scanf("%d",&n);
        switch(n){
            case 1:do_query(sockfd,&msg);break;
            case 2:do_history(sockfd,&msg);break;
            case 3:close(sockfd);exit(0);break;
        }
}
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值