C语言 Linux网络编程(C/S架构) 在线词典

Posted 铅笔小建

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言 Linux网络编程(C/S架构) 在线词典相关的知识,希望对你有一定的参考价值。

项目介绍

描述:
通过C/S架构实现在线词典,用户在客户端可以注册,登陆,然后可以查询单词,并且保存自己的单词查询记录。

知识点:

  • c语言进阶 Linux基础
  • C/S架构
  • 进程
  • sqlite3数据库
  • 时间函数
  • Makefile

效果图:


客户端

创建一个dict_client文件夹,存放客户端代码

client.h

#ifndef CLIENT_H
#define CLIENT_H
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

#define N 32

#define R 1 //user - register
#define L 2 //user - login
#define Q 3 //user - query
#define H 4 //user - history

//定义通信双方的信息结构体
typedef struct
    int type;
    char name[N];
    char data[256]; //password或word信息
MSG;

int do_register(int sockfd, MSG *msg);
int do_login(int sockfd, MSG *msg);
int do_query(int sockfd, MSG *msg);
int do_history(int sockfd, MSG *msg);
int client_connect(char *ip, int port);
#endif

cli_dict.c

#include "client.h"

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

    if(send(sockfd,msg,sizeof(MSG),0)<0)
    
        printf("fail to send.\\n");
        return -1;
    

    if(recv(sockfd,msg,sizeof(MSG),0)<0)
    
        printf("Fail to recv.\\n");
        return -1;
    
    //ok or user alread exist
    printf("%s\\n", msg->data);
    return 0;

int do_login(int sockfd, MSG *msg)
	msg->type = L;
    printf("Input name:");
    scanf("%s", msg->name);
    getchar();
    printf("Input password:");
    scanf("%s",msg->data);
    if(send(sockfd,msg,sizeof(MSG),0) < 0)
    
        printf("fail to send.\\n");
        return -1;
    
    if(recv(sockfd,msg,sizeof(MSG),0)<0)
    
        printf("fail to recv.\\n");
        return -1;
    
    if(strncmp(msg->data,"OK",3)==0)
    
        printf("OK\\n");
        return 1;
        
    else
        printf("%s\\n", msg->data);
    
    return 0;

int do_query(int sockfd, MSG *msg)
	puts("查询--------------");
    char name[10]=0;
    strcpy(name,msg->name);
    while(1)
        msg->type = Q;
        strcpy(msg->name,name);
        printf("Input word[quit:#]:");
        scanf("%s", msg->data);
        //printf("%s %s\\n",msg->name,msg->data);
        //客户端输入# 返回上一级菜单
        if(strncmp(msg->data,"#",1)==0)
            break;
        //将要查询的单词发送给服务器
        if(send(sockfd, msg, sizeof(MSG), 0)<0)
        
            printf("Fail to send.\\n");
            return -2;
        
        //等待接收服务器传递回来的单词注释信息
        if(recv(sockfd, msg, sizeof(MSG), 0) <  0)
        
            printf("Fail to recv.\\n");
            return -2;
        
        printf("%s\\n", msg->data);
    
    return 0;

int do_history(int sockfd, MSG *msg)
	msg->type = H;
    send(sockfd,msg,sizeof(MSG),0);
    printf("%s的查找记录--------\\n", msg->name);
    //接收服务器传递回来的历史记录信息
    while(1)
    
        recv(sockfd,msg,sizeof(MSG),0);
        if('\\0'==msg->data[0])
            break;
        //打印历史记录信息
        printf("%s\\n",msg->data);
    
    return 0;

int client_connect(char *ip, int port)
	int sockfd;
    struct sockaddr_in serveraddr;
    //创建流式套接字
    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
        perror("fail to socket.\\n");
        return -1;
    
    //给服务器地址初始化
    bzero(&serveraddr, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_addr.s_addr = inet_addr(ip);
    serveraddr.sin_port = htons(port);
    //连接服务器
    if(connect(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0)
        perror("fail to connect");
        return -1;
    
    return sockfd;

main.c

#include "client.h"
int main(int argc, char *argv[])
 
    int n,m;
    char dart1[32],dart2[32];
    MSG msg;
    if(argc != 3)
        printf("Usage:%s serverip port\\n", argv[0]);
        return -1;
    
    int sockfd = client_connect(argv[1], atoi(argv[2]));
    //一级菜单
    while(1)
    	
        printf("##################################################\\n");
        printf("*1.register         2.login               3.quit*\\n");
        printf("##################################################\\n");
        printf("Please choose:");
        scanf("%d", &n);
        getchar();
        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;
            default:
                printf("Invalid data cmd.\\n");
                n = 0;
                break;	//若没有break,输入aaa会执行3次switch
        
    
//二级菜单
next:  
    while(1)
    	
        printf("###########################################\\n");
        printf("*1.query        2.history           3.quit*\\n");
        printf("###########################################\\n");
        printf("Please choose:");
        
        getchar();
        scanf("%d", &m);
        switch(m)
            case 1:
                do_query(sockfd, &msg);
                break;
            case 2:
                do_history(sockfd, &msg);
                break;
            case 3:
                close(sockfd);
                exit(0);
                break;
            default:
                printf("Invalid data cmd.\\n");
                break;//若没有break,输入aaa会执行3次switch
        
    
    return 0;
 

Makefile

创建Makefile 文件,也可以不做这步,只是多敲几串命令而已,Makefile最大优点就是直接输入make命令就能编译文件,也挺方便。

cli: main.c cli_dict.c
	gcc *.c -o cli

服务器端

sqlite3

需要在linux中安装sqlite3,没有安装的输入这两条命令

sudo apt-get install sqlite3
sudo apt-get install libsqlite3-dev

然后创建数据库 sqlite3 dictionaryOL.db;
在sqlite3 shell中创建表

# 改变user表结构
CREATE TABLE user(id INTEGER PRIMARY KEY,name char unique,pwd char);
# 创建dict 存放字典内容(单词,含义)
CREATE TABLE dict(dict_id int primary key,word char,mean char);
# 统计字典里有多个意思的单词
select word from dict group by word having count(*)>=2;
# 创建record 记录用户所查询过的单词(姓名,时间,单词)
CREATE TABLE record(name char,date char,word char);

dict表需要自己插入单词和含义。

server.h

#ifndef SERVER_H
#define SERVER_H

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sqlite3.h>
#include <signal.h>
//时间函数
#include <time.h>
#include <unistd.h>
#define N 32

#define R 1 //user - register
#define L 2 //user - login
#define Q 3 //user - query
#define H 4 //user - history

//数据库
#define DATABASE "dictionaryOL.db"

//定义通信双方的信息结构体
typedef struct
    int type;
    char name[N];
    char data[256]; //password或word信息
MSG;
int do_client(int acceptfd,sqlite3 *db);
int do_register(int acceptfd, MSG *msg,sqlite3 *db);
int do_login(int acceptfd, MSG *msg,sqlite3 *db);
int do_query(int acceptfd, MSG *msg,sqlite3 *db);
int do_history(int acceptfd, MSG *msg,sqlite3 *db);
int search_callback(void *para,int f_num,char **f_value,char **f_name);
int history_callback(void *para,int f_num,char **f_value,char **f_name);
void get_date(char *date);
int do_client(int acceptfd,sqlite3 *db);
int server_init(char *ip, int port);

#endif

ser_dict.c

#include "server.h"

int do_register(int acceptfd, MSG *msg,sqlite3 *db)
	char *errmsg;
    char sql[512];
    sprintf(sql,"insert into user values(null,\\"%s\\",\\"%s\\");",msg->name,msg->data);
    printf("%s\\n", sql);
    if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
    
        printf("%s\\n", errmsg);
        strcpy(msg->data, "usr name already exist.");
    
    else
        printf("client register ok!\\n");
        strcpy(msg->data,"OK!");
    
    if(send(acceptfd,msg,sizeof(MSG),0)<0)
    
        perror("fail to send");
        return -1;
    
    return 0;

int do_login(int acceptfd, MSG *msg,sqlite3 *db)
	char sql[512] = 0;
    char *errmsg;
    int nrow;
    int ncloumn;
    char **resultp;
    sprintf(sql,
    "select * from user where name='%s' and pwd='%s';",
    msg->name,msg->data);
    printf("%s\\n", sql);
    if(sqlite3_get_table(db,sql,&resultp,
                &nrow,&ncloumn,&errmsg))
    
        printf("%s\\n", errmsg);
        return -1;
    
    if(nrow == 1)
    
        //查询成功,有此用户
        strcpy(msg->data,"OK");
        send(acceptfd,msg,sizeof(MSG),0);
        return 1;
    
    else
    
        //密码或者用户名错误
        strcpy(msg->data,"user/password/worng");
        send(acceptfd,msg,sizeof(MSG),0);
        return 0;
    
    return 1;

int do_query(int acceptfd, MSG *msg,sqlite3 *db)
	printf

Linux网络编程浅谈 C/S 和 B/S 架构

概述

在这个信息急剧膨胀的社会,我们不得不说人类正进入一个崭新的时代,那就是信息时代。信息时代的一个主要而显著的特征就是计算机网络的应用。计算机网络从最初的集中式计算,经过了Client/Server阶段(有两层C/S和三层C/S),已发展到目前最流行的 Browser/Server计算模式。其中颇具争论和影响力的是C/S以及B/S架构,C/S是一种历史悠久且技术非常成熟的架构,B/S是新生代架构,从C/S派生出来,有很多创新,在web信息时代虎虎生威。

\'【Linux网络编程】浅谈

 

C/S架构

一、C/S架构及其背景

C/S架构是一种比较早的软件架构,主要应用于局域网内。在这之前经历了集中计算模式,随着计算机网络的进步与发展,尤其是可视化工具的应用,出现过两层C/S和三层C/S架构,不过一直很流行也比较经典的是我们所要研究的两层C/S架构

\'【Linux网络编程】浅谈

C/S架构软件(即客户机/服务器模式)分为客户机和服务器两层:第一层是在客户机系统上结合了表示与业务逻辑,第二层是通过网络结合了数据库服务器。简单的说就是第一层是用户表示层,第二层是数据库层。

 

客户端和服务器直接相连,这两个组成部分都承担着重要的角色,第一层的客户机并不是只有输入输出,运算等能力,它可以处理一些计算,数据存储等方面的业务逻辑事务;第二层的服务器主要承担事务逻辑的处理,本来事务很重,但是由于客户机可以分担一些逻辑事务,所以减轻了服务器的负担,使得网络流量增多。

 

想要使用C/S架构的软件需要下载一个客户端,安装后就可以使用

 

二、C/S架构的优点

C/S架构既然能在计算机历史的长河中长盛不衰就必然有其闪光之处。下面将从各个角度分析C/S架构的优点。

1)客户端和服务器直接相连

 

2)客户端可以处理一些逻辑事务

 

3) 客户端操作界面

 

 

三、C/S架构的缺点

经过长期的时间检验,人们也发现了C/S存在的不足,下面将前人的观点整理总结一下。
1)客户端

 

 

2)服务器

 

3)用户

 


4)开发成本

 


5)后期成本

 

四、C/S架构应用

 

C/S架构的软件是在是数不胜数,从办公的OFFICE,WPS,WINRAR到杀毒软件如金山,瑞金再到我们的娱乐软件,如播放器,QQ,微信等,无处不见C/S架构。

 

B/S架构

一、B/S架构及其背景

随着Internet和WWW的流行,以往的主机/终端和C/S都无法满足当前的全球网络开放、互连、信息随处可见和信息共享的新要求,于是就出现了B/S型模式,即浏览器/服务器结构。它是C/S架构的一种改进,可以说属于三层C/S架构。主要是利用了不断成熟的WWW浏览器技术,用通用浏览器就实现了原来需要复杂专用软件才能实现的强大功能,并节约了开发成本,是一种全新的软件系统构造技术。

\'【Linux网络编程】浅谈

第一层是浏览器,即客户端,只有简单的输入输出功能,处理极少部分的事务逻辑。由于客户不需要安装客户端,只要有浏览器就能上网浏览,所以它面向的是大范围的用户,所以界面设计得比较简单,通用。

 

第二层是WEB服务器,扮演着信息传送的角色。当用户想要访问数据库时,就会首先向WEB服务器发送请求,WEB服务器统一请求后会向数据库服务器发送访问数据库的请求,这个请求是以SQL语句实现的。

 

第三层是数据库服务器,他扮演着重要的角色,因为它存放着大量的数据。当数据库服务器收到了WEB服务器的请求后,会对SQL语句进行处理,并将返回的结果发送给WEB服务器,接下来,WEB服务器将收到的数据结果转换为HTML文本形式发送给浏览器,也就是我们打开浏览器看到的界面。

 

B/S架构和C/S架构不同,浏览器不是直接和数据库服务器相连,所以是多对多的结构。因此在此结构下,很适合在广域网里实现巨大的互联网,甚至是全球网。有着很强大的信息共享性。

 

在B/S出现的早期,浏览器只能显示静态页面,得不到良好的交互,不能进行大量的逻辑处理,当时浏览器主要用来实现信息的发布,是一种单向的应用。后来出现了动态网页,这里的动态有三个方面,一是交互,二是动画,三是数据。这样,浏览器的交互性能得到极大提高。页面也越来越丰富多彩。浏览器也能处理部分逻辑事务,所以浏览器成为了客户端,但由于处理的内容较少,所以叫“瘦”客户端

 

 

二、B/S架构的优点

B/S架构是应WEB技术的飞速发展而从传统的C/S架构发展而来,并且一举成为当今主要的网络架构。目前主要的网站,尤其是商务网站都是基于B/S架构建立的。那么我们就来细数一下B/S架构的优点,它到底为什么受到大家的青睐。
1)浏览器

 

 


2)服务器

 


3)用户

 

 

4)成本

 

 

三、B/S架构的缺点

虽说B/S架构有很多优越性,但是也不可避免有些缺陷,不然也不会暴发究竟使用哪种架构的口水战。不过,在理论上,既然B/S是C/S的改进版,应该克服了C/S的很多缺陷,所以缺点应该不是很多。下面我们来看看实际上是什么情况。
1)客户端

 

 

2)服务器

 

 

四、B/S架构应用

当时在讲解典型的C/S架构时,提到了了常用的QQ软件。现在新出来了一个WEBQQ,从WEBQQ名称中的WEB就不难看出它属于B/S架构,是一种浏览器服务器结构。事实上也是如此,因为WEBQQ根本不需要安装客户端,只需要有浏览器就可以进行聊天交互了。

 

 

C/S和B/S

一、C/S和B/S关系概述

B/S架构是从C/S架构改进而来,可以说是三层C/S架构,由此可见两者关系不一般。B/S从C/S中脱离而出,后来随着WEB技术的飞速发展以及人们对网络的依赖程度加深,B/S一举成为当今最流行的网络架构。两种架构都在各自岗位上虎虎生威,它们各有千秋,都是非常重要的网络架构。在响应速度,用户界面,数据安全等方面,C/S强于B/S,但是在业务扩展和适用www条件下,B/S明显胜过C/S。可以这么说,B/S的强项就是C/S的弱项,反之亦然。它们各有优缺点,相互无法取代。

 

二、C/S和B/S的不同点

\'【Linux网络编程】浅谈  

1)比较大的差别
1、结构

C/S是两层架构,由客户端和服务器组成,而B/S是三层架构,由浏览器,WEB服务器和数据库服务器组成。


2、逻辑事务处理
C/S架构合理地让客户端和服务器承担一部分逻辑事务处理,使得服务器的负担减轻了,而且客户端也能进行一些数据处理和存储的功能。B/S架构的浏览器就是它的客户端,可是这个客户端只能进行一些简单的输入输出和信息发布共享的功能,主要的逻辑事务处理还是要靠服务器,所以服务器的负担很重。


3、工作原理
C/S架构是客户端和服务器直接相连,实现点对点的通信,B/S是浏览器通过WEB服务器向数据库服务器发送数据请求,实现多对多的通信。


4、响应速度
C/S架构的客户端和服务器直接相连,中间没有任何阻隔,所以相应速度快,尤其是在用户增多时更加明显。B/S架构相应速度慢,主要的重任在数据库服务器身上,由于B/S架构的无限扩展性,当用户激增,访问量庞大时,服务器相应速度慢,服务器存在瘫痪的危险。


5、成本
C/S架构开发时,硬件需要一次性购买,费用较高,且需要训练有素的技术人员,培训费用高,而且软件后期也需要不断投入大量资金。B/S架构只需要一次性投入几乎可以一劳永逸,有利于软件项目控制和IT黑洞。


6、维护、升级以及扩展
C/S架构一旦有业务的变更或要升级,客户端界面就要重新设计,需要投入大量的人力物力。软件维护也比较麻烦,需要专业人士进行维护。用户扩展也比较麻烦,需要安装客户端,对软硬件要求高。B/S架构的维护和升级都非常容易,只要更改页面内容或者增减页面即可,客户端几乎是零维护,只需要维护好服务器。所以相对来说更简易,方便。由于B/S可以随时随地的访问,所以极易扩展。


7、信息共享
C/S架构是建立在局域网之上的,面向的是可知的有限用户,信息共享只在小范围内。B/S架构建立在广域网之上,用户随时随地都可以访问,外部用户也可以访问,尤其是WEB技术的不断发展,B/S面对的是几乎无限的用户群体,所以信息共享性很强。


8、客户端界面
C/S架构可以针对不同的功能设计出不同的很有特色的用户界面,实现个性化。但是一旦业务改变就需要重新设计,很麻烦。B/S架构的用户界面很通用,不能针对用户突出个性,但是业务改变时只需要改变界面内容或者增减页面,很轻松就能实现。


2)小的差别
1、适用的网络
C/S架构是建立在局域网的基础之上的,局域网之间通过专用服务器提供连接提供服务。B/S架构是建立在广域网的基础之上,有更大的使用范围。


2、访问
C/S架构下,用户需要安装客户端才能够访问服务器,而B/S架构下,用户可以随时随地访问,只要有网有浏览器,方便快捷。  


3、数据库连接类型

C/S采用的是ODBC连接,所以只要用户连接了数据库就一直保持连接不会断开,所以限制了用户数,而B/S采用的是JDBC连接,用户并不保持对数据库的连接,所以用户数几乎是无限的。


4、功能
C/S架构能够实现单一的复杂功能,如财政管理等,所以现在大多数比较大型的ERP系统仍是C/S架构,B/S架构的界面比较通用,所能处理的逻辑事务较少,所以功能较弱。


5、安全性
C/S架构建立在局域网之上,面向比较固定的用户,对安全的要求较高。B/S架构建立在广域网上,面对不可知人群,安全性差。


6、信息流向不同
C/S 程序一般是典型的中央集权的机械式处理, 交互性相对低B/S 信息   流向可变化, B-B B-C B-G等信息、流向的变化, 更像个交易中心。


7、对技术人员的要求
C/S的功能比较专业化,对设计和开发人员的要求较高,需要专业的培训。B/S的界面比较人性化,通用化,所以不需要多高的技能。

 

 

以上是关于C语言 Linux网络编程(C/S架构) 在线词典的主要内容,如果未能解决你的问题,请参考以下文章

Python 3 socket编程

操作系统,C/S B/S架构,网络通信,

网络编程基础

网络编程之网络协议

网络编程

Python--网络编程-----C/S架构