电子词典项目

项目要求

在这里插入图片描述

项目实现分析

思维导图

在这里插入图片描述

1.基于tcp支持多客户端连接

所以要创建tcp并发服务器和一个tcp客户端,我选择tcp多线程并发服务器主线程用来连接客户端,子线程用来处理客户但请求

2.登陆注册功能,不能重复登录注册

创建一个用户表usr,包含用户名和密码。

不能重复注册,将用户名设为主键

不能重复登录,所以要再加一个标志位flag,用来判断用户是否在线,flag=1表示在线,flag=0表示离线,用户登陆前需判断此账号是否已经在线。登录成功将flag置1,用户下线将flag置0。

为了防止服务器意外退出,但其在线用户flag还未置零,所以每次重启服务器前要将所有用户flag置零。

3.将dict.txt导入数据库,单词查询历史记录功能

第一次服务器应该创建词典表dict,将dict.txt导入,包含单词和意思,防止因为多次启动服务器而导致多次导入词典造成数据重复,导入词典之前应该先判断是否已经存在该表

单词查询,先判断用户输入的是中文还是英文,中文需要用到模糊查找

历史记录功能,创建历史表history,包含用户名,查找内容,查找时间。

用户名和内容可以通过用户在查找的时候一并发送给服务器,所以客户端要记录登录成功时候的用户名,查找时间可以写一个获取当前时间的函数来获取。

完整代码
头文件

head.h

#ifndef __HEAD_H__
#define __HEAD_H__
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <fcntl.h>
#include <wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <semaphore.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/msg.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <sys/time.h>
#include <sys/select.h>
#include <poll.h>
#include <errno.h>
#include <sqlite3.h>
#define PRINT_ERR(msg) \
        do{\
        fprintf(stderr,"line:%d ",__LINE__);\
        perror(msg);\
        return -1;\
    } while(0)
#define IF(i) if (argc != i) {\
        printf("input error,try again\n");\
        printf("usage: ./a.out srcfile destfile\n");\
        return -1;\
}
#endif

此文件放在 /usr/include/目录下

服务器

tcptid_dict.c

#include <head.h>
#define PORT 8888
#define IP "192.168.10.159"

struct td
{
    int newfd;
    struct sockaddr_in cin_t;
};
sqlite3 *db;
void *callback(void *arg);
sqlite3 *init_dict();
int Users_logoff();
int init_tcpser(char *ip, int port);
int Tableisexist(char *name);
int handler(void *data, int argc, char **argv, char **azColName);
int dics_create();
int Login(int sfd);
int User_isonline(char *name);
int User_online(char *name);
int User_logoff(char *name);
int Register(int sfd);
int do_select(int sfd);
int do_history(char *name, char *news);
char *gettime();
int select_history(int sfd);
int main(int argc, const char *argv[])
{
    //初始化数据库并导入电子词库
    db = init_dict();
    //初始化tcp服务器
    int sfd = init_tcpser(IP, PORT);
    struct td td_t;
    socklen_t addrlen = sizeof(td_t.cin_t);
    pthread_t tid;
    while (1)
    {
        td_t.newfd = accept(sfd, (struct sockaddr *)&td_t.cin_t, &addrlen);
        if (td_t.newfd < 0)
            PRINT_ERR("accept");
        printf("[%s:%d] newfd:%d 成功连接\n", inet_ntoa(td_t.cin_t.sin_addr), ntohs(td_t.cin_t.sin_port), td_t.newfd);
        pthread_create(&tid, NULL, callback, (void *)&td_t);
        pthread_detach(tid);
    }
    close(sfd);

    return 0;
}
//子线程
void *callback(void *arg)
{
    struct td *p = (struct td *)arg;
    int newfd = p->newfd;
    struct sockaddr_in cin_t = p->cin_t;
    ssize_t res;
    char buf[2];
    while (1)
    {
        bzero(buf, sizeof(buf));
        //先只读取前两个字节判断其功能,剩余消息在功能函数读取
        res = recv(newfd, buf, 2, 0);
        if (res == 0)
        {
            printf("客户端断开,关闭newfd:%d\n", newfd);
            close(newfd);
            return NULL;
        }
        switch (buf[1])
        {
        case 1:
            printf("[%s:%d] newfd:%d请求注册\n", inet_ntoa(cin_t.sin_addr),
                   ntohs(cin_t.sin_port), newfd);
            Register(newfd);
            break;
        case 2:
            printf("[%s:%d] newfd:%d请求登录\n", inet_ntoa(cin_t.sin_addr),
                   ntohs(cin_t.sin_port), newfd);
            Login(newfd);
            break;
        case 3:
            printf("[%s:%d] newfd:%d请求查单词\n", inet_ntoa(cin_t.sin_addr),
                   ntohs(cin_t.sin_port), newfd);
            do_select(newfd);
            break;
        case 4:
            printf("[%s:%d] newfd:%d请求查询历史记录\n", inet_ntoa(cin_t.sin_addr),
                   ntohs(cin_t.sin_port), newfd);
            select_history(newfd);
            break;
        case 5:
            printf("[%s:%d] newfd:%d准备下线\n", inet_ntoa(cin_t.sin_addr),
                   ntohs(cin_t.sin_port), newfd);
            recv(newfd, buf, sizeof(buf), 0);
            User_logoff(buf);
            break;
        default:
            break;
        }
    }
}
//初始化数据库
sqlite3 *init_dict()
{
    if (sqlite3_open("sql.db", &db) != SQLITE_OK)
    {
        fprintf(stderr, "line:%d sqlite3_open:%s\n", __LINE__, sqlite3_errmsg(db));
        return NULL;
    }
    //将所有用户置于下线状态
    Users_logoff();
    //判断是否已经导入词典,存在则直接退出
    if (Tableisexist("dict") == 0)
    {
        printf("电子词典库准备完毕\n");
        return db;
    }
    //导入词典
    dics_create();
    printf("电子词典库准备完毕\n");
    return db;
}
//将所有用户置于下线状态
int Users_logoff()
{
    char sql[128] = "create table if not exists usr (name char primary key,password char,flag char);";
    char *errmsg = NULL;
    if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
    {
        fprintf(stderr, "line:%d sqlite3_exec:%s\n", __LINE__, errmsg);
        return -1;
    }
    //将所有用户flag置零
    sprintf(sql, "UPDATE usr SET flag='0';");
    if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
    {
        fprintf(stderr, "line:%d sqlite3_exec:%s\n", __LINE__, errmsg);
        return -1;
    }
    printf("%s\n",sql);
    return 0;
}
//判断是否存在表,存在返回1,否则返回0
int Tableisexist(char *name)
{
    char sql[128];
    sprintf(sql, "SELECT COUNT(*) FROM sqlite_master where type ='table' and name ='%s';", name);
    char *errmsg = NULL;
    int flag = 0;
    if (sqlite3_exec(db, sql, handler, (void *)&flag, &errmsg) != SQLITE_OK)
    {
        fprintf(stderr, "line:%d sqlite3_exec:%s\n", __LINE__, errmsg);
        return -1;
    }
    return flag == 1 ? 0 : -1;
}
int handler(void *data, int argc, char **argv, char **azColName)
{
    if (1 == argc)
    {//存在表,则将flag置1
        int iTableExist = atoi(*(argv));//如果存在表,*(argv)为"1"
        if (data != NULL)
        {
            int *ptr = (int *)data;
            *ptr = iTableExist;
        }
    }
    return 0;
}
//导入词典
int dics_create()
{
    printf("正在导入电子词典库,请稍后......\n");
    char sql[128] = "create table if not exists dict (word_s char,explain_s char);";
    char *errmsg = NULL;
    if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
    {
        fprintf(stderr, "line:%d sqlite3_exec:%s\n", __LINE__, errmsg);
        return -1;
    }
    FILE *fd = fopen("dict.txt", "r");
    if (fd == NULL)
        PRINT_ERR("fopen");
    fseek(fd, 0, SEEK_END);
    //记录文件大小
    int fileLen = ftell(fd);
    fseek(fd, 0, SEEK_SET);
    char word[40];
    char explain[60];
    char buf[100];
    int i;
    int count = 0;
    while (1)
    {//取一行单词和意思
        if (fgets(buf, sizeof(buf), fd) == NULL)
            break;
        //记录已读取的字节数
        count += strlen(buf);
        buf[strlen(buf) - 1] = 0;
        for (i = 0; i < strlen(buf); i++)
        {//防止单词中有一个空格的情况
            if (buf[i] == ' ' && buf[i + 1] == ' ')
            {
                buf[i] = 0;
                //提取单词
                strcpy(word, buf);
                break;
            }
        }
        for (int j = i + 1; j < strlen(buf+i+1) + i + 1; j++)
        {
            if (buf[j] != ' ')
            {//提取意思
                strcpy(explain, buf + j);
                break;
            }
        }
        //导入
        sprintf(sql, "INSERT INTO dict VALUES (\"%s\",\"%s\");", word, explain);
        if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
        {
            fprintf(stderr, "line:%d sqlite3_exec:%s\n", __LINE__, errmsg);
            return -1;
        }
        //显示已导入百分比
        printf("导入中..%%%.1f\r", (float)count / (fileLen / (100)));
        fflush(stdout);
    }
    return 0;
}
//初始化tcp服务器
int init_tcpser(char *ip, int port)
{
    //创建流式套接字
    int sfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sfd < 0)
        PRINT_ERR("socket");
    //允许端口快速重用
    int reuse = 1;
    if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
        PRINT_ERR("setsockopt");
    //填充地址信息的结构体,将IP和端口号绑定到套接字上
    struct sockaddr_in sin_t;
    sin_t.sin_family = AF_INET;
    sin_t.sin_port = htons(port);
    sin_t.sin_addr.s_addr = inet_addr(ip);
    //绑定服务器的ip和端口
    if (bind(sfd, (struct sockaddr *)&sin_t, sizeof(sin_t)) < 0)
        PRINT_ERR("bind");
    //将套接字设置为监听状态
    if (listen(sfd, 128) < 0)
        PRINT_ERR("listen");
    printf("服务器初始化完成\n");
    return sfd;
}
//客户端登录
int Login(int sfd)
{
    ssize_t res;
    char buf[50];
    //读取用户名和密码
    res = recv(sfd, buf, sizeof(buf), 0);
    if (res < 0)
        PRINT_ERR("recv");
    printf("用户名:%s 密码:%s\n", buf, buf + strlen(buf) + 1);
    char sql[128];
    char *errmsg = NULL;
    sprintf(sql, "select * from usr where name='%s';", buf);
    char **pres;
    int row, column;
    if (sqlite3_get_table(db, sql, &pres, &row, &column, &errmsg) != SQLITE_OK)
    {
        fprintf(stderr, "line:%d sqlite3_get_table:%s\n", __LINE__, errmsg);
        return -1;
    }
    //row=0,即没有查询结果,不存在用户
    if (row == 0)
    {
        //不存在该用户发送0
        printf("不存在该用户\n");
        buf[0] = 0;
        if (send(sfd, buf, 1, 0) < 0)
            PRINT_ERR("send");
    }
    //判断密码是否相同
    else if (strcmp(pres[4], buf + strlen(buf) + 1) == 0)
    {
        //判断用户是否在线
        if (User_isonline(buf) == 1)
        { //用户已在线发送3
            buf[0] = 3;
            if (send(sfd, buf, 1, 0) < 0)
                PRINT_ERR("send");
            return -1;
        }
        //将用户flag置1
        User_online(buf);
        //登录成功发送1
        printf("登录成功\n");
        buf[0] = 1;
        if (send(sfd, buf, 1, 0) < 0)
            PRINT_ERR("send");
    }
    else
    {
        //密码不对发送2
        printf("%s\n", pres[3]);
        printf("密码不正确\n");
        buf[0] = 2;
        if (send(sfd, buf, 1, 0) < 0)
            PRINT_ERR("send");
    }
    return 0;
}
//判断用户是否在线,在线为1,反之为0
int User_isonline(char *name)
{
    char sql[128];
    sprintf(sql, "select flag from usr where name='%s';", name);
    char *errmsg = NULL;
    char **pres;
    int row, column;
    if (sqlite3_get_table(db, sql, &pres, &row, &column, &errmsg) != SQLITE_OK)
    {
        fprintf(stderr, "line:%d sqlite3_get_table:%s\n", __LINE__, errmsg);
        return -1;
    }
    //判断flag是否为1
    if (strcmp(pres[1],"1")==0)
        return 1;
    else
        return 0;
}
//用户上线,将flag置1
int User_online(char *name)
{
    char sql[128];
    sprintf(sql, "UPDATE usr SET flag='1' WHERE name='%s';", name);
    char *errmsg = NULL;
    if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
    {
        fprintf(stderr, "line:%d sqlite3_exec:%s\n", __LINE__, errmsg);
        return -1;
    }
    return 0;
}
//用户下线,将flag置1
int User_logoff(char *name)
{
    char sql[128];
    sprintf(sql, "UPDATE usr SET flag='0' WHERE name='%s';", name);
    char *errmsg = NULL;
    if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
    {
        fprintf(stderr, "line:%d sqlite3_exec:%s\n", __LINE__, errmsg);
        return -1;
    }
    return 0;
}
//客户端注册
int Register(int sfd)
{
    ssize_t res;
    char buf[50];
    //读取用户名和密码
    res = recv(sfd, buf, sizeof(buf), 0);
    if (res < 0)
        PRINT_ERR("recv");
    printf("用户名:%s 密码:%s\n", buf, buf + strlen(buf) + 1);
    char sql[128];
    char *errmsg = NULL;
    //导入用户表,默认flag为0
    sprintf(sql, "INSERT INTO usr VALUES (\"%s\",\"%s\",\"%s\");", buf, buf + strlen(buf) + 1, "0");
    if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
    {
        printf("注册失败,已有该用户\n");
        buf[0] = 0;
        //注册失败向客户端发送0
        if (send(sfd, buf, 1, 0) < 0)
            PRINT_ERR("send");
        return -1;
    }
    printf("注册成功\n");
    buf[0] = 1;
    //注册成功向客户端发送1
    if (send(sfd, buf, 1, 0) < 0)
        PRINT_ERR("send");
    return 0;
}
//查单词
int do_select(int sfd)
{
    ssize_t res;
    char buf[50];
    char sql[128];
    //读取用户名和要查询的内容
    res = recv(sfd, buf, sizeof(buf), 0);
    if (res < 0)
        PRINT_ERR("recv");
    printf("%s搜索'%s'\n", buf, buf + strlen(buf) + 1);
    //将信息导入历史记录表
    do_history(buf, buf + strlen(buf) + 1);
    //判断是查询单词还是意思
    if (buf[strlen(buf) + 1] >= 'a' && buf[strlen(buf) + 1] <= 'z')
        sprintf(sql, "select * from dict where word_s=\"%s\";", buf + strlen(buf) + 1);
    else
        sprintf(sql, "select * from dict where explain_s  LIKE \"%%%s%%\";", buf + strlen(buf) + 1);
    char **pres;
    char *errmsg = NULL;
    int row, column;
    if (sqlite3_get_table(db, sql, &pres, &row, &column, &errmsg) != SQLITE_OK)
    {
        fprintf(stderr, "line:%d sqlite3_get_table:%s\n", __LINE__, errmsg);
        return -1;
    }
    if (row == 0)
    { //没有查询到发送0
        sql[0] = 0;
        if (send(sfd, sql, 1, 0) < 0)
            PRINT_ERR("send");
        return 0;
    }
    for (int i = column; i + 1 < (row + 1) * column; i += 2)
    {//将每条单词和意思合为一组,循环发送
        sprintf(sql, "%-15s %s\n", pres[i], pres[i + 1]);
        if (send(sfd, sql, sizeof(sql), 0) < 0)
            PRINT_ERR("send");
    }
    //发送完,发送1表示发送完毕
    sql[0] = 1;
    if (send(sfd, sql, 1, 0) < 0)
        PRINT_ERR("send");
    sqlite3_free_table(pres);
    return 0;
}
//将信息导入历史记录
int do_history(char *name, char *news)
{
    char sql[128] = "create table if not exists history (name char,news char,time char);";
    char *errmsg = NULL;
    if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
    {
        fprintf(stderr, "line:%d sqlite3_exec:%s\n", __LINE__, errmsg);
        return -1;
    }
    //获取时间
    char *times = gettime();
    sprintf(sql, "INSERT INTO history VALUES (\"%s\",\"%s\",\"%s\");", name, news, times);
    if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
    {
        fprintf(stderr, "line:%d sqlite3_exec:%s\n", __LINE__, errmsg);
        return -1;
    }
    return 0;
}
//获取当前时间
char *gettime()
{
    time_t ts;
    struct tm *tm;
    char *times = (char *)malloc(50);
    ts = time(NULL);
    tm = localtime(&ts);
    sprintf(times, "%d-%02d-%02d %02d:%02d:%02d", tm->tm_year + 1900,
            tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
    return times;
}
//客户端查询历史信息
int select_history(int sfd)
{
    ssize_t res;
    char buf[50];
    char sql[128];
    //读取用户名
    res = recv(sfd, buf, sizeof(buf), 0);
    if (res < 0)
        PRINT_ERR("recv");
    sprintf(sql, "select * from history where name='%s';", buf);
    char **pres;
    char *errmsg = NULL;
    int row, column;
    if (sqlite3_get_table(db, sql, &pres, &row, &column, &errmsg) != SQLITE_OK)
    {
        fprintf(stderr, "line:%d sqlite3_get_table:%s\n", __LINE__, errmsg);
        return -1;
    }
    if (row == 0)
    { //没有查询到发送0
        sql[0] = 0;
        if (send(sfd, sql, 1, 0) < 0)
            PRINT_ERR("send");
        return 0;
    }
    for (int i = 0; i + 2 < (row + 1) * column; i += 3)
    {
        sprintf(sql, "%-15s\t%-15s\t%-20s\t\n", pres[i], pres[i + 1], pres[i + 2]);
        if (send(sfd, sql, sizeof(sql), 0) < 0)
            PRINT_ERR("send");
    }
    //发送完,再次发送1表示发送完毕
    sql[0] = 1;
    if (send(sfd, sql, 1, 0) < 0)
        PRINT_ERR("send");
    sqlite3_free_table(pres);
    return 0;
}
客户端

tcpcli_dict.c

#include <head.h>
#define PORT 8888
#define IP "192.168.10.159"

typedef void (*sighandler_t)(int);
void handler(int sig);
int init_tcpcli(char *ip, int port);
int LR_page(int sfd);
int main_page(int sfd);
int Login(int sfd, char *name);
int Register(int sfd);
int dict_select(int sfd);
int select_history(int sfd);
int end(int sfd);
char my_name[20];
int sfd;
int main(int argc, const char *argv[])
{
    //初始化tcp客户端
    sfd = init_tcpcli(IP, PORT);
    //捕获ctrl+c信号
    signal(2, handler);

LD: //登录注册页面
    if (LR_page(sfd) == -1)
    { //返回值为-1,说明用户选择退出
        goto END1;
    }
    //主页面
    int a = main_page(sfd);
    if (a == -1)
    { //返回值为-1,说明用户选择退出
        goto END2;
    }
    else if (a == 1)
    { //返回值为1,说明用户选择返回,返回前先下线账号
        end(sfd);
        //返回上一级退出当前账号,将用户名清空
        bzero(my_name,sizeof(my_name));
        goto LD;
    }
END2:
    end(sfd);
END1:
    //用户还未登录不用发送离线消息
    close(sfd);
    return 0;
}
//捕捉信号后的处理函数
void handler(int sig)
{
    //判断用户是否已登录,还未登录不用发送离线消息
    if (strlen(my_name) != 0)
        end(sfd);
    close(sfd);
    exit(0);
}
//初始化客户端
int init_tcpcli(char *ip, int port)
{
    //创建流式套接字
    int sfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sfd < 0)
        PRINT_ERR("socket");
    struct sockaddr_in sin_t;
    sin_t.sin_family = AF_INET;
    sin_t.sin_port = htons(port);
    sin_t.sin_addr.s_addr = inet_addr(ip);
    if (connect(sfd, (struct sockaddr *)&sin_t, sizeof(sin_t)) < 0)
        PRINT_ERR("connect");
    printf("成功连接服务器[%s:%d]\n", inet_ntoa(sin_t.sin_addr), ntohs(sin_t.sin_port));
    return sfd;
}
//登录注册页面
int LR_page(int sfd)
{
    char c;
    while (1)
    {
        system("clear");
        printf("*******************\n");
        printf("*******1.登录******\n");
        printf("*******2.注册******\n");
        printf("*******3.退出******\n");
        printf("*******************\n");
        printf("请输入>>>");
        c = getchar();
        while (getchar() != 10)
            ;
        switch (c)
        {
        case '1':
            c = Login(sfd, my_name);
            break;
        case '2':
            Register(sfd);
            break;
        case '3':
            return -1;
        default:
            printf("请输入正确的选项\n");
            break;
        }
        if (c == 1)
        {
            printf("输入任意字符跳转>>>");
            while (getchar() != 10)
                ;
            break;
        }
        printf("输入任意字符清屏>>>");
        while (getchar() != 10)
            ;
    }
    return 0;
}
//主页面
int main_page(int sfd)
{
    while (1)
    {
        system("clear");
        printf("**************************\n");
        printf("*******1.查单词***********\n");
        printf("*******2.查看历史记录******\n");
        printf("*******3.返回上一级********\n");
        printf("*******4.退出**************\n");
        printf("**************************\n");
        printf("请输入>>>");
        char c = getchar();
        while (getchar() != 10)
            ;
        switch (c)
        {
        case '1':
            dict_select(sfd);
            break;
        case '2':
            select_history(sfd);
            break;
        case '3':;
            return 1;
            break;
        case '4':
            return -1;
            break;
        default:
            printf("请输入正确的选项\n");
            break;
        }
        printf("输入任意字符清屏>>>");
        while (getchar() != 10)
            ;
    }
    return 0;
}
//查单词
int dict_select(int sfd)
{
    char word[50];
    char buf[128];
    while (1)
    {
        system("clear");
        printf("请输入要查找的单词或中文(输入#退出)\n");
        scanf("%s", word);
        if (word[0] == '#')
        {
            while (getchar() != 10)
                ;
            return 0;
        }
        while (getchar() != 10)
            ;
        //封装数据包,3代表查单词
        int size = sprintf(buf, "%c%c%s%c%s%c", 0, 3, my_name, 0, word, 0);
        if (send(sfd, buf, size, 0) < 0)
            PRINT_ERR("send");
        while (1)
        {
            if (recv(sfd, buf, sizeof(buf), 0) < 0)
                PRINT_ERR("recv");
            if (buf[0] == 0)
            {
                printf("无该单词\n");
                break;
            }
            else if (buf[0] == 1)
            {
                printf("查询完毕\n");
                break;
            }
            else
                printf("%s", buf);
        }
        printf("输入任意字符清屏>>>");
        while (getchar() != 10)
            ;
    }
}
//查看历史记录
int select_history(int sfd)
{
    char buf[128];
    //封装数据包,4代表查记录
    int size = sprintf(buf, "%c%c%s%c", 0, 4, my_name, 0);
    if (send(sfd, buf, size, 0) < 0)
        PRINT_ERR("send");
    while (1)
    {
        if (recv(sfd, buf, sizeof(buf), 0) < 0)
            PRINT_ERR("recv");
        if (buf[0] == 0)
        {
            printf("无记录\n");
            break;
        }
        else if (buf[0] == 1)
        {
            printf("查询完毕\n");
            break;
        }
        else
            printf("%s", buf);
    }
    return 0;
}
//登录
int Login(int sfd, char *my_name)
{
    char name[20];
    char password[30];
    char buf[50];
    printf("请输入用户名和密码\n");
    printf("(用户名和密码用空格隔开)\n");
    scanf("%s %s", name, password);
    while (getchar() != 10)
        ;
    //封装数据包,2代表登录
    int size = sprintf(buf, "%c%c%s%c%s%c", 0, 2, name, 0, password, 0);
    if (send(sfd, buf, size, 0) < 0)
        PRINT_ERR("send");
    if (recv(sfd, buf, 1, 0) < 0)
        PRINT_ERR("recv");
    if (buf[0] == 1)
    {
        strcpy(my_name, name);
        printf("登录成功\n");
        return 1;
    }
    else if (buf[0] == 0)
        printf("不存在该用户\n");
    else if (buf[0] == 2)
        printf("密码不正确\n");
    else if (buf[0] == 3)
        printf("账号已在别处登录\n");
    return 0;
}
//注册
int Register(int sfd)
{
    char name[20];
    char password[30];
    char buf[50];
    printf("请输入要注册的用户名和密码\n");
    printf("(用户名和密码用空格隔开)\n");
    scanf("%s %s", name, password);
    while (getchar() != 10)
        ;
    //封装数据包,1代表注册
    int size = sprintf(buf, "%c%c%s%c%s%c", 0, 1, name, 0, password, 0);
    if (send(sfd, buf, size, 0) < 0)
        PRINT_ERR("send");
    if (recv(sfd, buf, 1, 0) < 0)
        PRINT_ERR("recv");
    if (buf[0] == 1)
        printf("注册成功\n");
    else
        printf("注册失败,已存在该用户\n");
    return 0;
}
//下线
int end(int sfd)
{
    char buf[50];
    //封装数据包,5代表该用户下线
    int size = sprintf(buf, "%c%c%s%c", 0, 5, my_name, 0);
    if (send(sfd, buf, size, 0) < 0)
        PRINT_ERR("send");
    return 0;
}
项目运行结果

在这里插入图片描述

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值