一、简介
1、项目环境:Linux Ubuntu 16.04操作系统、C/C++语言
2、开发工具:Vim编辑器、g++4.8编译器、Makefile脚本、mysql数据库
3、技术关键:C++面向对象设计思想、基于TCP协议的网络编程技术、线程池技术
4、项目描述:项目基于Linux操作系统实现,采用C/S模式,使用TCP协议模拟ATM终端与服务器的通信过程。同时,本项目还在Server端创建了固定数量的线程池,用以减小创建线程时的开销,应对突发性大量请求。
二、项目目录结构
三、数据库设计
card.sql
create database card;
use card;
create table card_info(
_id_num char(20) primary key not null,
_name char(20) not null,
_card_num char(20),
_pswd char(8),
_money bigint
);
四、代码设计
myalgorithm.hpp
#pragma once
#include<string>
#include<vector>
vector<string> split_string(string str)
{
vector<string> ret;
string s;
for(int i = 2; i < str.size(); i++)
{
if(str[i] == ' ')
{
ret.push_back(s);
s.clear();
}
else
{
s += str[i];
if(i == str.size() - 1)
{
ret.push_back(s);
}
}
}
return ret;
}
tcp_socket.hpp
#pragma once
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<string>
#include<cassert>
#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<fcntl.h>
typedef struct sockaddr sockaddr;
typedef struct sockaddr_in sockaddr_in;
#define CHECK_RET(exp) if(!(exp)){return false;}
class tcp_socket
{
private:
int _fd;
public:
tcp_socket():_fd(-1)
{
}
tcp_socket(int fd):_fd(fd)
{
}
bool _socket()
{
_fd = socket(AF_INET, SOCK_STREAM, 0);
if(_fd < 0)
{
perror("socket");
return false;
}
return true;
}
bool _close() const
{
close(_fd);
return true;
}
bool _bind(const std::string& ip, uint16_t port) const
{
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(ip.c_str());
addr.sin_port = htons(port);
int ret = bind(_fd, (sockaddr *)&addr, sizeof(addr));
if(ret < 0)
{
perror("bind");
return false;
}
return true;
}
bool _listen(int num) const
{
int ret = listen(_fd, num);
if(ret < 0)
{
perror("listen");
return false;
}
return true;
}
bool _accept(tcp_socket *peer, std::string *ip = nullptr, uint16_t *port = nullptr) const
{
sockaddr_in peer_addr;
socklen_t len = sizeof(peer_addr);
int new_sock = accept(_fd, (sockaddr *)&peer_addr, &len);
if(new_sock < 0)
{
perror("accept");
return false;
}
peer->_fd = new_sock;
if(ip != nullptr)
{
*ip = inet_ntoa(peer_addr.sin_addr);
}
if(port != nullptr)
{
*port = ntohs(peer_addr.sin_port);
}
return true;
}
bool _recv(std::string *buf) const
{
buf->clear();
char tmp[1024 * 10] = {
};
ssize_t read_size = recv(_fd, tmp, sizeof(tmp), 0);
if(read_size < 0)
{
perror("recv");
return false;
}
if(read_size == 0)
{
return false;
}
buf->assign(tmp, read_size);
return true;
}
bool _send(const std::string& buf) const
{
ssize_t write_size = send(_fd, buf.data(), buf.size(), 0);
if(write_size < 0)
{
perror("send");
return false;
}
return true;
}
bool _connect(const std::string& ip, uint16_t port) const
{
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(ip.c_str());
addr.sin_port = htons(port);
int ret = connect(_fd, (sockaddr *)&addr, sizeof(addr));
if(ret < 0)
{
perror("connect");
return false;
}
return true;
}
int _get_fd() const
{
return _fd;
}
};
thread_pool.hpp
#pragma once
#include"../include/tcp_socket.hpp"
#include<iostream>
#include<queue>
#include<pthread.h>
#include<unistd.h>
#include<time.h>
#include<functional>
#define MAX_THREAD 5
typedef std::function<void (const std::string& req, std::string *resp)> Handler;
struct thread_arg
{
tcp_socket new_sock;
std::string ip;
uint16_t port;
Handler handler;
};
typedef bool (*handler_t)(thread_arg *);
using namespace std;
class ThreadTask
{
private:
thread_arg *_data;
handler_t _handler;
public:
ThreadTask(thread_arg *data, handler_t handler)
:_data(data),_handler(handler)
{
}
void setTask(thread_arg *data, handler_t handler)
{
_data = data;
_handler = handler;
}
void run()
{
_handler(_data);
}
};
class ThreadPool
{
private:
int _thread_max;
int _thread_cur;
bool _tp_quit;
queue<ThreadTask