基于linux下的在线电子词典

这是一个C语言实现的TCP/IP通信客户端和服务器的代码示例。客户端可以进行注册、登录、查询和查看历史记录的操作,服务器端处理这些请求并与数据库交互。代码中包含了SQLite数据库操作,用于存储用户信息和历史记录。

client.c

#include<stdio.h>
#include<string.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<linux/in.h>
#include<stdlib.h>

//消息数据包
typedef struct msg
{
    int type;//类型
    char name[128];//用户名
    char data[256];//内容
}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);
int main(int argc, const char *argv[])
{
    if(argc < 3)
    {
        printf("input : %s<ip> <port>\n",argv[0]);
        exit(0);
    }
    MSG msg;
    int login = 0;
    //创建套节字文件
    int sockfd;
    if((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0)
    {
        perror("sockfd err.\n");
        return -1;
    }
    printf("socket yes.\n");
    //填充结构体数组
    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]);

    //允许重用本地地址 和端口号     
    int optval = 1;
    socklen_t optval_len = sizeof(optval);
    setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&optval,optval_len);

    socklen_t addrlen = sizeof(serveraddr);
    //连接服务器
    if(connect(sockfd,(struct sockaddr *)&serveraddr,addrlen) < 0)
    {
        perror("connect err.\n");
        return -1;
    }
    printf("connect yes\n");
    char buf[128] = {0};
    int n = 0;
    while(1)
    {   //注册.登录.退出
        printf("*******************************\n");
        printf("* 1:register  2:login  3:quit *\n");
        printf("*******************************\n");
        printf("please choose>>>");
        if(scanf("%d",&n) == 0)
        {
            fgets(buf,sizeof(buf),stdin);
            buf[strlen(buf) -1] = '\0';
            continue;
        }
        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);
        }
    }

void do_register(int sockfd,MSG *msg)
{
    //封装注册msg包
    msg->type = 'R';
    printf("please user name:");
    scanf("%s",msg->name);
    printf("please user code:");
    scanf("%s",msg->data);
    //向服务器发送注册包
    send(sockfd,msg,sizeof(MSG),0);
    //接收服务器反馈
    recv(sockfd,msg,sizeof(MSG),0);
    printf("register: %s\n",msg->data);
    return;
}
int do_login(int sockfd,MSG *msg)
{
    //封装登录包
    msg->type = 'L';
    printf("please user name:");
    scanf("%s",msg->name);
    printf("please user code:");
    scanf("%s",msg->data);
    //发送登录消息
    send(sockfd,msg,sizeof(MSG),0);
    //接收服务器反馈
    recv(sockfd,msg,sizeof(MSG),0);
    //判断是否登录成功
    if(strncmp(msg->data,"OK",3) == 0)
    {
        printf("login OK.\n");
        return 1;
    }
    printf("login:%s\n",msg->data);
    return 0;
}
void do_query(int sockfd,MSG *msg)    
{   //封装查询包
    msg->type = 'Q';
    while(1)
    {
        printf("query word:");
        scanf("%s",msg->data);
        if(strcmp(msg->data,"#") == 0)
            break;
         //发送查询信号
        send(sockfd,msg,sizeof(MSG),0);
         //接收服务器反馈
        recv(sockfd,msg,sizeof(MSG),0);
        //printf优化解释,打印
        printf("%s\n",msg->data);

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

Makefile 

 

all:
    gcc server.c -lsqlite3 -o fwq    
    gcc client.c -o khd

clean:
    rm fwq khd
 

Sever.c 

 #include<stdio.h>
#include<sqlite3.h>
#include<string.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<sys/socket.h>

//消息数据包
typedef struct 
{
    int type;//类型
    char name[128];//用户名
    char data[256];//内容
}MSG;
int callback(void *arg,int f_num,char **f_value,char **f_name);
void get_date(char *date);
int do_searchword(int acceptfd, MSG *msg);
void do_register(int acceptfd,MSG *msg,sqlite3 *db);
void do_login(int acceptfd,MSG *msg,sqlite3 *db);
void do_query(int acceptfd,MSG *msg,sqlite3 *db);
void do_history(int acceptfd,MSG *msg,sqlite3 *db);
int main(int argc, const char *argv[])
{
    if(argc < 3)
    {
        printf("input :%s,<ip> <port>\n",argv[0]);
        exit(0);
    }
    sqlite3 *db;
    char *errmsg = NULL;
    int sockfd,acceptfd;
    ssize_t recvaddr;
    MSG  msg;
    char buf[128] = {0};
    //创建一个数据库文件
    if(sqlite3_open("str.db",&db) != 0)
    {
        fprintf(stderr,"sqlite3_open failed:%s\n",sqlite3_errmsg(db));
        return -1;
    }
    printf("open yes.\n");
    //添加一个用户信息表,key表明注册的用户名只能唯一
    if(sqlite3_exec(db,"create table str(name char primary key,code char);",NULL,NULL,&errmsg) != 0)
    {
        fprintf(stderr,"create str failed:%s\n",errmsg);
    }
    printf("exec yes.\n");
    //添加一个历史记录的表
    if(sqlite3_exec(db,"create table record(name char,time char,word char);",NULL,NULL,&errmsg) != 0)
    {
        fprintf(stderr,"create record failed:%s\n",errmsg);
    }
    //创建一个套节字文件
    if((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0)
    {
        perror("socket err.\n");
        return -1;
    }
    printf("socket yes.\n");
    //填充结构体数组
    struct sockaddr_in serveraddr,clinentaddr;
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(atoi(argv[2]));
    serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); 

    //允许重用本地地址 和端口号     
    int optval = 1;
    socklen_t optval_len = sizeof(optval);
    setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&optval,optval_len);

    socklen_t serverlen = sizeof(serveraddr);
    socklen_t clinentlen = sizeof(clinentaddr);
    //绑定
    if(bind(sockfd,(struct sockaddr *)&serveraddr,serverlen) < 0)
    {
        perror("bind err.\n");
        return -1;
    }
    printf("bind yes.\n");
    //监听
    if(listen(sockfd,8) < 0)
    {
        perror("listen err.\n");
        return -1;
    }
    printf("listen yes.\n");

    //信号处理函数
    signal(SIGCHLD,SIG_IGN);

    pid_t pid;
    while(1)
    {   //阻塞等待连接
        if((acceptfd = accept(sockfd,NULL,NULL)) < 0)
        {
            perror("acceptfd err.\n");
            return -1;
        }
        printf("accept yes.\n");
        //创建进程
        if((pid = fork()) < 0)
        {
            perror("fork err.\n");
            return -1;
        }
        else if(pid == 0)
        {
            //循环接收客户端数据存放到msg包里
            while(recvaddr = recv(acceptfd,&msg,sizeof(msg),0) > 0) 
            {
                //根据类型处理
                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;
                }
            }
            printf("ip%sclient quit!!!!\n",(char *)inet_ntoa(clinentaddr.sin_addr.s_addr));
            close(acceptfd);
            exit(0);
        }
        else
        {
            printf("** user login. **\n");
        }
    }
    close(sockfd);
    return 0;
}

完整代码请参考:  https://download.youkuaiyun.com/download/signal___/18161310?spm=1001.2014.3001.5501

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

signal___

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值