服务器程序流程:
![](https://img-blog.csdnimg.cn/img_convert/824660bf320888673fe27dc95011ad32.png)
*. 定义消息结构体:
![](https://img-blog.csdnimg.cn/img_convert/2af2b204a5027d86f1496bcaf65306fe.png)
输出参数:
![](https://img-blog.csdnimg.cn/img_convert/4fb012670a15f33c68cfae507c39a624.png)
打开数据库:
![](https://img-blog.csdnimg.cn/img_convert/e9f82dee1de719c3940a547c09cd0826.png)
建立服务器端网络连接
一,TCP多进程连接:
建立套接字
![](https://img-blog.csdnimg.cn/img_convert/b25b109ae2a39419c01a1d2626694fd3.png)
填充自己的网络地址:
![](https://img-blog.csdnimg.cn/img_convert/6ab4b9b3102ab478c6bfa4c549d2e91d.png)
绑定
![](https://img-blog.csdnimg.cn/img_convert/10015d2de000369d39a4fc9502f0d5ab.png)
监听
![](https://img-blog.csdnimg.cn/img_convert/f8f70cb8ca1d9dc61bda652b00ac38ee.png)
连接(采用父子进程的方式,父进程连接,每连接一个,就创建子进程进行服务)
![](https://img-blog.csdnimg.cn/img_convert/7e87ca18a08efac090bf849f836f470e.png)
do_client()应为do_server(),写错了
实现服务器功能:
![](https://img-blog.csdnimg.cn/img_convert/065b2734149489eec6c9111425450e72.png)
服务器框架代码实现:
#include<stdio.h>
#include<stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include<strings.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include<unistd.h>
#include<sqlite3.h>
#include<signal.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 "my.db"
//defines the information structure of both sides of the communication
typedef struct{
int type;
char name[N];
char data[256];
}MSG;
void do_register(int sockfd,MSG *mag,sqlite3 *db);
int do_login(int sockfd, MSG* mag,sqlite3 *db);
int do_query(int sockfd, MSG* mag,sqlite3 *db);
int do_history(int sockfd, MSG* mag,sqlite3 *db);
int do_server(int acceptfd,sqlite3 *db);
//do_register
void do_register(int sockfd,MSG *mag,sqlite3 *db)
{
printf("register ...\n");
}
//do_login
int do_login(int sockfd, MSG* mag,sqlite3 *db)
{
printf("login...\n");
return 1;
}
//do_query
int do_query(int sockfd, MSG* mag,sqlite3 *db)
{
printf("query...\n");
return 1;
}
//do_history
int do_history(int sockfd, MSG* mag,sqlite3 *db)
{
printf("finding history...\n");
return 0;
}
//./server 192.168.3.196 10000
int main(int argc,const char* argv[])
{
//Robustness
if(argc !=3){
printf("Usage:%s serverip port.\n",argv[0]);
return -1;
}
//massage struct
MSG msg;
sqlite3 *db;
int acceptfd;
pid_t pid;
//open sqlite
if(sqlite3_open(DATABASE,&db)!=SQLITE_OK){
printf("%s\n",sqlite3_errmsg(db));
return -1;
}
else{
printf("open DATABASE success.\n");
}
//socket
int sockfd;
if((sockfd=socket(AF_INET,SOCK_STREAM,0))<0){
perror("socket");
exit(1);
}
//padding
//bzero
struct sockaddr_in serveraddr;
bzero((void*)&serveraddr,sizeof(serveraddr));
//fill
serveraddr.sin_family=AF_INET;
serveraddr.sin_addr.s_addr=inet_addr(argv[1]);
serveraddr.sin_port=htons(atoi(argv[2]));
//bind
if(bind(sockfd,(struct sockaddr*)&serveraddr,sizeof(serveraddr))<0){
perror("bind");
exit(1);
}
//listen
if(listen(sockfd,5)<0){
perror("listen");
exit(1);
}
//handle die process
signal(SIGCHLD,SIG_IGN);
//accept
while(1){
if((acceptfd=accept(sockfd,NULL,NULL))<0){
perror("fail to accept");
return -1;
}
if((pid=fork())<0){
perror("fail to fork");
return -1;
}
else if(pid==0){
//handle client
close(sockfd);
do_server(acceptfd,db);
}
else {
close(acceptfd);
}
}
return 0;
}
int do_server(int acceptfd,sqlite3 *db)
{
MSG msg;
while(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;
default:
printf("Invalid data msg.\n");
}
}
close(acceptfd);
exit(0);
return 0;
}
服务器数据库:
数据库中数据存储的结构:
1.用户信息和查询历史
用两个表实现
2.在线词典库
数据库的创建
![](https://img-blog.csdnimg.cn/img_convert/2125e580ee7b91f2470e65b6006cadc3.png)
在数据库中建立两个表:
![](https://img-blog.csdnimg.cn/img_convert/c3c964839e3a3539ff53594ea16ffd12.png)
![](https://img-blog.csdnimg.cn/img_convert/30b5cee35fafcdf5c8d4ab0f70053be3.png)