文章目录
1. 游客黑名单项目
1.1 项目简介
实现语言:c/c++
服务模型:client – server
第三方库:libevent,json,mysql
客户端模型:分布式协同处理+多线程
服务器模型:半同步半异步+MVC
1.2 项目服务介绍
游客黑名单项目用于记录各个景区内出现不文明行为的游客信息。当游客需要进入景区时候需要进行验证是否存在于黑名单之上,如果已被列入黑名单,景区有权拒绝该游客进入。
项目客户端主要负责黑名单信息的增删改查操作,获取到操作指令之后将指令发送给服务器。服务器负责存储黑名单数据,并在接收到客户端的操作指令之后进行相应的操作,操作完成后返回操作结果。
2. 项目准备
2.1 如何将数据共享范围扩大?
答:依赖网络
- 问题提出:什么是网络?
服务器和客户端
服务器:提供服务,数据存储,数据处理,
客户端:接受数据,提供给用户和服务器交流的工具
- 问题提出:什么是互联网?
2.2 图解
3. 项目
3.1 面临问题
-
如何将 一个请求的数据需要打包成一条进行发送?
-
每一种请求需要对应一个标识码?
3.2 客户端框架
3.2.1 图示
问题提出:
- 一个进程最多可以打开多少个套接字?
答:1024
3.2.2 数据通讯方式
- 如何区分receiver拿到的是Blacker的数据还是selecter的数据?
- 拿到了receiver的数据如何发送给对应select
selecter的数据只有TYPE_BLACKER_SEARCH类型的数据,在selecter发送的数据包中加上对应的select的fd。
套接字的作用域是整个进程,在其他线程中打开的套接字在本线程依然可以使用。
3.3 服务器封装
tcp_cli.h
//封装tcp/ip
#ifndef TCP_CLI_H
#define TCP_CLI_H
#include<iostream>
#include<string.h>
#include<string>
#include<json/json.h>
#include<errno.h>
#include<arpa.inet.h>
using namespace std;
class tcpClient
{
public:
tcpClient()
{
_connectFd = -1;
}
//0 fail 1 success
int Connect(const string& ip, const unsigned short port)
{
if (-1 == _connectFd)
{
return 0;
}
_ip = ip;
_port = port;
int _connectFd = socket(AF_INET, SOCK_STREAM, 0);
if(-1== _connectFd)
{
cerr << "clifd creat fail:errnoz:" << errno << endl;
return 0;
}
struct sockaddr_in saddr;
saddr.sin_family = AF_INET;
saddr.sin_port = htons(_port);
saddr.sin_addr.s_addr = inet_addr(ip.c_str());
return connect(_connectFd, (struct sockaddr*)&saddr, sizeof(saddr));
}
int GetConnectFd()//获取套接字
{
return _connectFd;
}
string GetIP()
{
return _ip;
}
unsigned short int GetPort()
{
return _port;
}
int Send(const string& massage)
{
return send(_connectFd, massage.c_str(), strlen(massage.c_str()), 0);
}
int Recv(string& str)
{
char buff[1024] = {0};
int ret = recv(_connectFd, buff, 1023, 0);
str = buff;
return ret;
}
private:
int _connectFd;
string _ip;
unsigned short int _port;
};
#endif
tcp_cli_only.h
//单例模式
#ifndef TCP_CLI_ONLY
#define TCP_CLI_ONLY
#include<iostream>
#include"tcp_cli.h"
#include<mutex>
using namespace std;
class tcpClientOnly
{
public:
int connect(const string& ip, const unsigned short port)
{
return _tcpclient.Connect(ip, port);
}
int GetConnectFd()
{
return _tcpclient.GetConnectFd();
}
string GetIp()
{
return _tcpclient.GetIp();
}
unsigned short int GetPort()
{
return _tcpclient.GetPort();
}
int Send(const string& massage)
{
return _tcpclient.Send(massage);
}
int Recv(string& str)
{
return _tcpclient.Recv(str);
}
static tcpClientOnly* Get_Only_Tcp_Client(const string& ip, const unsigned short port)
{
if (NULL == _only_Tcp_Client)//为了防止每次进来都要加锁,变成双重if判断
{
_lock.lock();
if (NULL == _only_Tcp_Client)
{
_only_Tcp_Client = new tcpClientOnly();
}
_lock.unlock();
}
return _only_Tcp_Client;
}
private:
tcpClientOnly(const string& ip, const unsigned short port){}
static tcpClientOnly* _only_Tcp_Client;
static mutex _lock;
tcpClient _tcpclient;
};
#endif
tcp_cli_only.cpp
#include"tcp_cli_only.h"
tcpClientOnly* tcpClientOnly::_only_Tcp_Client = NULL;
mutex tcpClientOnly::_lock = mutex();