Linux C实现的在线词典(基于TCP)

4 篇文章 1 订阅
4 篇文章 0 订阅

基本功能

  1. 注册
  2. 登录
  3. 查询
  4. 查看查询记录

源码

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

#define  N  16
#define  R  1   //  user register
#define  L  2   //  user login
#define  Q  3   //  query word
#define  H  4   //  history record
#define  COL 50
#define  F  0
#define  S  100

#define DATABASE "my.db"

typedef struct sockaddr SA;

typedef struct 
{
    int type;
    char name[N];
    char data[256];   // password or word or remark
} MSG;


服务器端:

#include"head_server.h"

void do_register(int connfd, MSG *pbuf, sqlite3 *db)
{
    char sqlstr[128];
    char *errmsg;

    sprintf(sqlstr, "insert into usr values ('%s', '%s')", pbuf->name, pbuf->data);
    printf("%s\n", sqlstr);
    if (sqlite3_exec(db, sqlstr, NULL, NULL, &errmsg) != SQLITE_OK)
    {
        sqlite3_free(errmsg);
        sprintf(pbuf->data, "user %s already exist!!!", pbuf->name);
    }
    else
    {
        strncpy(pbuf->data, "OK", 256);
    }
    send(connfd, pbuf, sizeof(MSG), 0);

    return;
}

void do_login(int connfd,MSG *msg,sqlite3 *db)
{
    char sqlopt[128];
    char *errmsg,**result;
    int r, c;

    sprintf(sqlopt, "select * from usr where name = '%s' and pass = '%s'", msg -> name, msg -> data);
    if (sqlite3_get_table(db, sqlopt, &result, &r, &c, &errmsg) != SQLITE_OK)
    {
        printf("error:%s\n",errmsg);
    }
    if(r == 0)
    {
        msg -> type = F;
    }
    else
    {
        msg -> type = S;
    }
    send(connfd, msg, sizeof(MSG), 0);
}

int do_search(int connfd, MSG *msg)
{
    FILE *fp;
    char str[300];
    int result,len;
    char *p;
    if((fp = fopen("dict.txt", "r")) == NULL)
    {
        strcpy(msg -> data, "File can't be opened!!!");
        send(connfd, msg, sizeof(MSG), 0);
        return -1;
    }
    len = strlen(msg -> data);
    printf("%s\n", msg -> data);
    while(fgets(str,300,fp) != NULL)
    {
        result = strncmp(msg -> data,str,len);
        if(result > 0)
        {
            continue;
        }           
        if(result < 0 || str[len] != ' ')
        {
            break;
        }
        p = str + len;
        while(*p == ' ')
            p ++;
        strcpy(msg -> data, p);
        printf("%s\n",msg -> data);
        send(connfd, msg, sizeof(MSG), 0);

        fclose(fp);

        return 1;
    }
    strcpy(msg -> data, "Word can't be found!!!");
    send(connfd, msg, sizeof(MSG), 0);
    fclose(fp);
    return 0;
}

void get_date(char date[])
{
    time_t t;
    struct tm *tp;
    time(&t);
    tp = localtime(&t);
    strftime(date, 64, "%Y-%m-%d %H:%M:%S", tp);
}
int do_query(int connfd,MSG *msg,sqlite3 *db)
{
    char date[64];
    char word[64];
    char sqlstr[100];
    char *errmsg;
    strcpy(word,msg -> data);
    if(do_search(connfd, msg) != 1)
        return -1;

    get_date(date);
    sprintf(sqlstr, "insert into record values ('%s', '%s', '%s')", msg->name,date, word);
    if (sqlite3_exec(db, sqlstr, NULL, NULL, &errmsg) != SQLITE_OK)
    {
        printf("error : %s\n", errmsg);
        sqlite3_free(errmsg);
    }
}

int history_callback(void *arg, int f_num, char **f_value, char **f_name)
{

    //f_value 每个记录的值    
    //f_num 记录中包含的字段个数
    //f_name  每个记录的字段名称
    int connfd;
    MSG buf;
    connfd = *(int *)arg;

    sprintf(buf.data, "%s : %s", f_value[1], f_value[2]);
    send(connfd, &buf, sizeof(buf), 0);

    return 0;
}

void do_history(int connfd, MSG *msg, sqlite3 *db)
{
    char sqlstr[128], *errmsg;

    sprintf(sqlstr, "select * from record where name = '%s'", msg->name);
    if (sqlite3_exec(db, sqlstr, history_callback, (void *)&connfd, &errmsg) != SQLITE_OK)
    {
        printf("error : %s\n", errmsg);
    }
    msg->data[0] = '\0';
    send(connfd, msg, sizeof(MSG), 0);

}


void do_menu(int connfd, sqlite3 *db)
{
    MSG msg;
    while( recv(connfd, &msg, sizeof(msg), 0) > 0)
    {
        switch(msg.type)
        {
        case R:
            do_register(connfd,&msg,db);
            break;
        case L:
            do_login(connfd,&msg,db);
            break;
        case Q:
            do_query(connfd,&msg,db);
            break;
        case H:
            do_history(connfd, &msg, db);
            break;
        }
    }
    printf("client quit\n");
    exit(0);

}
int main(int argc, char *argv[])
{
    int listenfd, connfd;
    struct sockaddr_in myaddr;
    pid_t pid;
    MSG buf;
    sqlite3 *db;

    if (argc < 3)
    {
        printf("Usage : %s <ip> <port>\n", argv[0]);
        exit(-1);
    }

    if (sqlite3_open(DATABASE, &db) != SQLITE_OK)
    {
        printf("error : %s\n", sqlite3_errmsg(db));
        exit(-1);
    }
    if ((listenfd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
    {
        perror("fail to socket");
        exit(-1);
    }

    bzero(&myaddr, sizeof(myaddr));
    myaddr.sin_family = PF_INET;
    myaddr.sin_port = htons(atoi(argv[2]));
    myaddr.sin_addr.s_addr = inet_addr(argv[1]);
    if (bind(listenfd, (SA *)&myaddr, sizeof(myaddr)) < 0)
    {
        perror("fail to bind");
        exit(-1);
    }

    if (listen(listenfd, 5) < 0)
    {
        perror("fail to listen");
        exit(-1);
    }

    signal(SIGCHLD, SIG_IGN);

    while ( 1 )
    {
        if ((connfd = accept(listenfd, NULL, NULL)) < 0)
        {
            perror("fail to accept");
            exit(-1);
        }

        if ((pid = fork()) < 0)
        {
            perror("fail to fork");
            exit(-1);
        }
        else if (pid == 0)
        {
            do_menu(connfd,db);
        }
        close(connfd);
    }

    return 0;
}

客户端:

#include"head_client.h"

void do_register(int sockfd, MSG *msg)
{
    msg->type = R;
    printf("Please input name : ");
    scanf("%s", msg->name);
    printf("Please input password : ");
    scanf("%s", msg->data);

    send(sockfd, msg, sizeof(MSG), 0);
    recv(sockfd, msg, sizeof(MSG), 0);
    printf("Register : %s\n", msg->data);

}
/**************************************************************/

int do_login(int sockfd,MSG *msg)
{
    memset(msg,0,sizeof(msg)); 
    msg -> type = L;
    printf("Please input name : ");
    scanf("%s", msg->name);
    printf("Please input password : ");
    scanf("%s", msg->data);

    send(sockfd, msg, sizeof(MSG), 0);
    recv(sockfd, msg, sizeof(MSG), 0);

    if(msg -> type == F)
    {
        printf("LOGIN:name or password is wrong!!!\n");
        return 0;
    }
    else
    {
        printf("LOGIN: OK\n");
        return 1;
    }
}

/******************************************************************/

int do_query(int sockfd,MSG *msg)
{
    msg -> type = Q;
    while(1)
    {
    printf("Please inputs words : ");
    scanf("%s", msg->data);
    if(strncmp(msg -> data, "#",  2) == 0) 
        break;
    send(sockfd, msg, sizeof(MSG), 0);
    recv(sockfd, msg, sizeof(MSG), 0);
    printf("Explain:   %s\n", msg->data);
    }
}

/****************************************************************/

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


int main(int argc, char *argv[])
{
    int sockfd, login = 0;
    struct sockaddr_in servaddr;
    MSG msg;
    char clean[64];

    if (argc < 3)
    {
        printf("INPUT ERROR\n", argv[0]);
        exit(-1);
    }

    if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
    {
        perror("Fail to socket");
        exit(-1);
    }

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = PF_INET;
    servaddr.sin_port = htons(atoi(argv[2]));
    servaddr.sin_addr.s_addr = inet_addr(argv[1]);

    if (connect(sockfd, (SA *)&servaddr, sizeof(servaddr)) < 0)
    {
        perror("Fail to connect");
        exit(-1);
    }

    int n;

front:

    while ( 1 )
    {
        printf("\n");
        printf("************************************\n");
        printf("* 1: Register   2: Login   3: Quit *\n");
        printf("************************************\n");
        printf("\n");
        printf("Please choose : ");
        if (scanf("%d", &n) == 0)
        {
            fgets(clean, 64, stdin);
            printf("\n");
            continue;
        }
        switch ( n )
        {
        case 1 :
            printf("\n");
            do_register(sockfd, &msg);
            printf("\n");
            break;
        case 2 :
            printf("\n");
            if (do_login(sockfd, &msg) == 1)
            {
                printf("\n");
                goto next;
            }
            printf("\n");
            break;
        case 3 :
            close(sockfd);
            exit(0);
        }
    }

    //the second menu
next:
    while (1)
    {
        printf("****************************************************\n");
        printf("* 1: Query word    2: History word    3: Main menu *\n");
        printf("****************************************************\n");
        printf("please choose : ");

        if (scanf("%d", &n) == 0)
        {
            fgets(clean, 64, stdin);
            printf("\n");
            continue;
        }
        switch ( n )
        {
        case 1 :
            printf("\n");
            do_query(sockfd, &msg);
            printf("\n");
            break;
        case 2 :
            printf("\n");
            do_history(sockfd, &msg);
            printf("\n");
            break;
        case 3 :
            goto front;
        }
    }

    return 0;
}
Linux 大全; 按照A~Z区分; A a−Linux a−Linux is an x86 floppy−based mini−distribution, where assembly code meets Linux kernel. It contains only programs written in assembly language. It is extemely small, yet functional, and provides HTTP and FTP services out−of−the−box. Initial version 0.17 was released August 17, 2002. A floppy−based distribution. From LWN Distribution List http://www.tldp.org/LDP/Linux−Dictionary/html/index.html a2p Awk to Perl translator From whatis http://www.tldp.org/LDP/Linux−Dictionary/html/index.html a2ps GNU a2ps 'Anything to PostScript' converter and pretty−printer a2ps converts files into PostScript for printing or viewing. It uses a nice default format, usually two pages on each physical page, borders surrounding pages, headers with useful information (page number, printing date, file name or supplied header), line numbering, symbol substitution as well as pretty printing for a wide range of programming languages. Historically, a2ps started as a text to PostScript converter, but thanks to powerful delegations it is able to let you use it for any kind of files, ie it can also digest manual pages, dvi files, texinfo, .... Among the other most noticeable features of a2ps are: − various encodings (all the Latins and others), − various fonts (automatic font down loading), − various medias, − various printer interfaces, − various output styles, − various programming languages, − various helping applications, − and various spoken languages. From Debian 3.0r0 APT http://www.tldp.org/LDP/Linux−Dictionary/html/index.html a2ps The a2ps filter converts text and other types of files to PostScript format. A2ps has pretty−printing capabilities and includes support for a wide number of programming languages, encodings (ISO Latins, Cyrillic, etc.), and media. From Redhat 8.0 RPM http://www.tldp.org/LDP/Linux−Dictionary/html/index.html a52dec Utilities to extract and decode ATCS A/52 streams Utilities to extract and decode ATCS A/52 streams. The A/52 standard is used in a variety of applications, including digital television and DVD. It is also known as AC−3. From Debian 3.0r0 APT http://www.tldp.org/LDP/Linux−Dictionary/html/index.html AA Auto Answer (MODEM) From VERA http://www.tldp.org/LDP/Linux−Dictionary/html/index.html aa3d An ASCII art stereogram generator This program generates the well known and popular random dot stereograms in ASCII art. From Debian 3.0r0 APT http://www.tldp.org/LDP/Linux−Dictionary/html/index.html AAA Authentication, Authorization and Accounting From VERA http://www.tldp.org/LDP/Linux−Dictionary/html/index.html AAC Advanced Audio Coding (IIS, MPEG) From VERA http://www.tldp.org/LDP/Linux−Dictionary/html/index.html AAC Authorization and Access Control (IETF) From VERA http://www.tldp.org/LDP/Linux−Dictionary/html/index.html AAD Authorized AutoCAD Dealer (AutoCAD, CAD) From VERA http://www.tldp.org/LDP/Linux−Dictionary/html/index.html A
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值