网络编程项目(云词典项目)

目录

一、功能要求

服务器

用户客户端

二、演示效果 

1.登录、注册功能

2. 查单词功能

3.查看历史纪录功能

三、项目代码 

1.头文件

2.服务器

3.用户端

四、B站讲解视频


一、功能要求

仿照云词典的原理,实现云词典功能,用户可以查询输入的单词的英文解释,也可以查看历史记录。

服务器

处理客户端的请求,并将数据存入数据库中,客户端请求的数据从数据库进行获取,服务器转发给客户端。

用户客户端

实现账号的注册、登录功能,当登录成功时可以查单词、查看历史记录等功能。

二、演示效果 

1.登录、注册功能

2. 查单词功能

3.查看历史纪录功能

三、项目代码 

1.头文件

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sqlite3.h>
#include <signal.h>
#include <time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/select.h>

struct word_msg
{
    char word[20];   // 单词
    char parse[256]; // 含义
};

typedef struct
{
    int acceptfd;         // 链接客户端
    unsigned char type;   // 功能类型 R:注册 L:登录 Q:查询 H:历史记录
    char name[32];        // 用户名
    char password[32];    // 密码
    char buf[1024];       // 调试信息
    struct word_msg msgg; // 单词信息
} MSG;

2.服务器

#include "head.h"

fd_set readfds, tempfds;
sqlite3 *db;
MSG msg;

void zhuce(MSG *msg);  // 注册
void denglu(MSG *msg); // 登录
void chaxun(MSG *msg); // 查询
void lishi(MSG *msg);  // 历史

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        printf("用法:<port>\n");
        return -1;
    }
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    printf("sorkfd:%d\n", sockfd);

    struct sockaddr_in saddr, caddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(atoi(argv[1]));
    saddr.sin_addr.s_addr = INADDR_ANY;
    socklen_t addrlen = sizeof(saddr);

    if (bind(sockfd, (struct sockaddr *)&saddr, addrlen) < 0)
    {
        perror("bind失败");
        close(sockfd);
        return -1;
    }
    printf("bind成功\n");

    if (listen(sockfd, 7) < 0)
    {
        perror("lisren失败");
        close(sockfd);
        return -1;
    }
    printf("listen成功\n");

    // 打开数据库
    if (sqlite3_open("./yuncidian.db", &db) < 0)
    {
        printf("打开数据库失败: %s\n", sqlite3_errmsg(db));
        return -1;
    }

    FD_ZERO(&readfds);
    FD_ZERO(&tempfds);
    FD_SET(sockfd, &readfds);
    int max = sockfd;
    while (1)
    {
        tempfds = readfds;
        int ret = select(max + 1, &tempfds, NULL, NULL, NULL);
        if (ret == -1)
        {
            perror("select失败");
            close(sockfd);
            return -1;
        }
        if (FD_ISSET(sockfd, &tempfds))
        {
            int acceptfd = accept(sockfd, (struct sockaddr *)&caddr, &addrlen);
            if (acceptfd < 0)
            {
                perror("accept失败\n");
                return -1;
            }
            printf("客户端ip:%s\t 端口号:%d\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port));
            FD_SET(acceptfd, &readfds);
            if (max < acceptfd)
            {
                max = acceptfd;
            }
        }
        for (int i = sockfd + 1; i <= max; i++)
        {
            if (FD_ISSET(i, &tempfds))
            {
                int ret = recv(i, &msg, sizeof(msg), 0);
                msg.acceptfd = i;
                if (ret < 0)
                {
                    perror("recv失败");
                    close(sockfd);
                    return -1;
                }
                else if (ret == 0)
                {
                    printf("客户端acceptfd:%d退出\n", i);
                    FD_CLR(i, &readfds);
                    close(i);
                    while (!FD_ISSET(max, &readfds))
                    {
                        max--;
                    }
                }
                else
                {
                    printf("%c\n", msg.type);
                    switch (msg.type)
                    {
                    case 'R':
                        zhuce(&msg);
                        break;
                    case 'L':
                        denglu(&msg);
                        break;
                    case 'Q':
                        chaxun(&msg);
                        break;
                    case 'H':
                        lishi(&msg);
                        break;
                    default:
                        break;
                    }
                }
            }
        }
    }
    return 0;
}

void zhuce(MSG *msg) // 注册
{
    memset(msg->buf, 0, sizeof(msg->buf));
    char *errmsg = NULL;
    char sql[128];
    char check_sql[128];
    char **result = NULL;
    int rows, columns;
    while (1)
    { // 检查用户名是否已存在
        sprintf(check_sql, "select * from user where name='%s';", msg->name);
        if (sqlite3_get_table(db, check_sql, &result, &rows, &columns, &errmsg) != 0)
        {
            sprintf(msg->buf, "查询失败: %s", errmsg);
            break;
        }
        if (rows > 0)
        {
            sprintf(msg->buf, "用户名已存在");
            break;
        }
        // 执行插入操作
        sprintf(sql, "insert into user values('%s','%s');", msg->name, msg->password);
        if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != 0)
        {
            sprintf(msg->buf, "注册失败: %s", errmsg);
            break;
        }
        else
        {
            printf("%s\n", sql);
            sprintf(msg->buf, "注册成功");
            break;
        }
    }
    send(msg->acceptfd, msg->buf, sizeof(msg->buf), 0);
}
void denglu(MSG *msg) // 登录
{
    memset(msg->buf, 0, sizeof(msg->buf));
    char sql[128];
    char *errmsg = NULL;
    char **result = NULL;
    int rows, columns;
    while (1)
    {
        sprintf(sql, "select * from user where name = '%s' and password = '%s';", msg->name, msg->password);
        // 执行 SQL 查询
        int sqlget = sqlite3_get_table(db, sql, &result, &rows, &columns, &errmsg);
        if (sqlget != 0)
        {
            sprintf(msg->buf, "sqlite3_get_table错误%s", errmsg);
            break;
        }
        else if (rows > 0)
        {
            sprintf(msg->buf, "登录成功");
            break;
        }
        else
        {
            sprintf(msg->buf, "登录失败");
            break;
        }
    }
    send(msg->acceptfd, msg->buf, strlen(msg->buf), 0);
}
void chaxun(MSG *msg) // 查询
{
    memset(msg->buf, 0, sizeof(msg->buf));
    char sql[1024];
    char sql1[1024];
    char *errmsg = NULL;
    char **result = NULL;
    int rows, columns;
    time_t t;
    struct tm *timeinfo;
    char date[100];
    time(&t);
    timeinfo = localtime(&t);
    while (1)
    {
        snprintf(date, sizeof(date), "%d-%d-%d %d:%d:%d", timeinfo->tm_year + 1900, timeinfo->tm_mon + 1, timeinfo->tm_mday, timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
        snprintf(sql, sizeof(sql), "select parse from dic where word='%s';", msg->msgg.word);
        snprintf(sql1, sizeof(sql1), "insert into history values ('%s','%s','%s');", msg->name, date, msg->msgg.word);
        if (sqlite3_exec(db, sql1, NULL, NULL, &errmsg) != 0)
        {
            sprintf(msg->buf, "放入历史记录失败: %s", errmsg);
            break;
        }
        printf("%s\n", sql1);
        int rc = sqlite3_get_table(db, sql, &result, &rows, &columns, &errmsg);
        if (rc != 0)
        {
            sprintf(msg->buf, "查询失败: %s", errmsg);
        }
        else
        {
            if (rows > 0)
            {
                for (int i = 1; i <= rows; ++i)
                {
                    strcat(msg->buf, "查询到的单词信息:");
                    strcat(msg->buf, result[i * columns]);
                    strcat(msg->buf, "\n");
                }
                printf("%s\n", sql);
                break;
            }
            else
            {
                strcpy(msg->buf, "没有找到该单词信息.");
                break;
            }
        }
    }
    send(msg->acceptfd, msg->buf, strlen(msg->buf) - 1, 0);
}
void lishi(MSG *msg) // 历史
{
    printf("%s\n", msg->name);
    char sql[1100];
    char *errmsg = NULL;
    char **result = NULL;
    int rows, columns;
    while (1)
    {
        sprintf(sql, "select date,word from history where name='%s';", msg->name);
        memset(msg->buf, 0, sizeof(msg->buf));

        int rc = sqlite3_get_table(db, sql, &result, &rows, &columns, &errmsg);
        if (rc != 0)
        {
            sprintf(msg->buf, "查询历史记录失败: %s", errmsg);
            break;
        }
        else
        {
            if (rows > 0)
            {
                for (int i = 1; i <= rows; ++i)
                {
                    strcat(msg->buf, "查询到的信息:");
                    for (int j = 0; j < columns; ++j)
                    {
                        strcat(msg->buf, result[i * columns + j]);
                        strcat(msg->buf, " ");
                    }
                    strcat(msg->buf, "\n");
                }
                break;
            }
            else
            {
                strcpy(msg->buf, "该历史记录不存在");
                break;
            }
        }
    }
    send(msg->acceptfd, msg->buf, strlen(msg->buf) - 1, 0);
}

3.用户端

#include "head.h"

int flag = 0;
fd_set readfds, tempfds;
sqlite3 *db;
MSG msg;

void denglujiemian();    // 登录界面
void yuncidianjiemian(); // 云词典界面
void zhuce(MSG *msg);    // 注册
void denglu(MSG *msg);   // 登录
void chaxun(MSG *msg);   // 查询
void lishi(MSG *msg);    // 历史

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        printf("用法:<port>\n");
        return -1;
    }

    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        perror("socket err");
        return -1;
    }

    struct sockaddr_in saddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(atoi(argv[1]));
    saddr.sin_addr.s_addr = inet_addr("192.168.50.214");
    socklen_t addrlen = sizeof(saddr);

    if (connect(sockfd, (struct sockaddr *)&saddr, addrlen) < 0)
    {
        perror("connect err");
        return -1;
    }
    printf("connect 成功\n");

    while (1)
    {
        memset(msg.buf, 0, sizeof(msg.buf));
        msg.acceptfd = sockfd;
        if (flag == 0)
        {
            denglujiemian(); // 登录界面
        }
        if (flag == 1)
        {
            yuncidianjiemian(); // 云词典界面
        }

        printf("请输入选项: ");
        scanf(" %c", &msg.type);
        printf("msg.type:%c\n", msg.type);
        switch (msg.type)
        {
        case 'R':
            zhuce(&msg); // 注册
            break;
        case 'L':
            denglu(&msg); // 登录
            break;
        case 'Q':
            chaxun(&msg); // 查询
            break;
        case 'H':
            lishi(&msg); // 历史
            break;
        case 'D':
            flag = 0; // 返回登录菜单
            break;
        default:
            break;
        }
    }
    // 6.关闭
    close(sockfd);
    return 0;
}

void denglujiemian() // 登录界面
{
    printf("************************************\n");
    printf("* R: register   L: login   D: quit *\n");
    printf("************************************\n");
}
void yuncidianjiemian() // 云词典界面
{
    printf("***********************************************\n");
    printf("* Q: query_word   H: history_record   D: quit *\n");
    printf("***********************************************\n");
}

void zhuce(MSG *msg) // 注册
{
    memset(msg->name, 0, sizeof(msg->name));
    memset(msg->password, 0, sizeof(msg->password));
    printf("请输入用户名:");
    scanf("%s", msg->name);
    getchar();
    printf("请输入用户密码:");
    scanf("%s", msg->password);
    getchar();
    send(msg->acceptfd, msg, sizeof(*msg), 0);
    recv(msg->acceptfd, msg->buf, sizeof(msg->buf), 0);
    printf("%s\n", msg->buf);
}
void denglu(MSG *msg) // 登录
{
    while (1)
    {
        memset(msg->name, 0, sizeof(msg->name));
        memset(msg->password, 0, sizeof(msg->password));
        printf("请输入用户名:");
        scanf("%s", msg->name);
        getchar();
        printf("请输入用户密码:");
        scanf("%s", msg->password);
        getchar();
        send(msg->acceptfd, msg, sizeof(*msg), 0);
        recv(msg->acceptfd, msg->buf, sizeof(msg->buf), 0);
        printf("%s\n", msg->buf);
        if (strcmp(msg->buf, "登录成功") == 0)
        {
            flag = 1;
            break;
        }
        if (strcmp(msg->buf, "登录失败") == 0)
        {
            continue;
        }
    }
}
void chaxun(MSG *msg) // 查询
{
    while (1)
    {
        memset(msg->buf, 0, sizeof(msg->buf));
        memset(msg->msgg.word, 0, sizeof(msg->msgg.word));
        printf("请输入要查询的单词(输入#退出查询):");
        scanf("%s", msg->msgg.word);
        getchar();
        if (strcmp(msg->msgg.word, "#") == 0)
        {
            break;
        }
        else
        {
            send(msg->acceptfd, msg, sizeof(*msg), 0);
            recv(msg->acceptfd, msg->buf, sizeof(msg->buf), 0);
            printf("%s\n", msg->buf);
            continue;
        }
    }
}
void lishi(MSG *msg) // 历史
{
    send(msg->acceptfd, msg, sizeof(*msg), 0);
    recv(msg->acceptfd, msg->buf, sizeof(msg->buf), 0);
    printf("%s\n", msg->buf);
}

四、B站讲解视频

http://【24071_网路编程_云词典项目_何物爱惜雨】 https://www.bilibili.com/video/BV1Yt4behEb1/?share_source=copy_web&vd_source=f25867d1b9870033386a3e5ea1bbca6e

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值