小编个人主页详情<—请点击 小编个人gitee代码仓库<—请点击 linux系统编程专栏<—请点击 linux网络编程专栏<—请点击 倘若命中无此运,孤身亦可登昆仑,送给屏幕面前的读者朋友们和小编自己! 
目录
-
- 前言
- 一、线程池版
-
- 简单打印
-
- Task.hpp
- TcpClient.cc
- TcpServer.hpp
- 测试
- 断线自动重连
-
- 测试
- 英汉翻译
-
- 测试
- 二、源代码
-
- TcpServer.hpp
- Main.cc
- TcpClient.cc
- Tash.hpp
- Init.hpp
- ThreadPool.hpp
- Log.hpp
- makefile
- dict.txt
- 总结
前言
【linux】网络套接字编程(五)TCP服务器与客户端的实现——多进程版,多线程版——书接上文 详情请点击<——,本文会在上文的基础上进行讲解,所以对上文不了解的读者友友请点击前方的蓝字链接进行学习 本文由小编为大家介绍——【linux】网络套接字编程(六)TCP服务器与客户端的实现——线程池版,客户端如何实现断线自动重连,服务器与客户端实现英汉翻译
一、线程池版
简单打印
Task.hpp
#pragma once
#include <iostream>
#include <string>
#include <cstring>
#include <unistd.h>
#include "Log.hpp"
extern Log lg;
class Task
{
public:
Task()
{}
Task(int sockfd, const std::string& clientip, const uint16_t& clientport)
: sockfd_(sockfd)
, clientip_(clientip)
, clientport_(clientport)
{}
void operator()()
{
char inbuffer[4096];
ssize_t n = read(sockfd_, inbuffer, sizeof(inbuffer) – 1);
if (n > 0)
{
inbuffer[n] = 0;
std::cout << "client say# " << inbuffer << std::endl;
std::string echo_string = "tcpserver echo# ";
echo_string += inbuffer;
n = write(sockfd_, echo_string.c_str(), echo_string.size());
if(n < 0)
lg(Info, "write err, errno: %d, errstr: %s", errno, strerror(errno));
}
else if(n == 0)
{
lg(Info, "%s:%d quit, server colse sockfd: %d", clientip_.c_str(), clientport_, sockfd_);
}
else
{
//异常
lg(Warning, "read error, sockfd: %d, client ip: %s, client port: %d",
sockfd_, clientip_.c_str(), clientport_);
}
close(sockfd_);
}
~Task()
{}
private:
int sockfd_;
std::string clientip_;
uint16_t clientport_;
};
static void* HandlerTask(void* args)
{
ThreadPool* tp = static_cast<ThreadPool*>(args);
std::string name = tp->GetThreadName(pthread_self());
while(true)
{
tp->Lock();
while(tp->IsQueueEmpty())
{
tp->ThreadSleep();
}
T t = tp->Pop();
tp->Unlock();
t();
// std::cout << name << " run" << ", result: " << t.GetResult() << std::endl;
}
return nullptr;
}
TcpClient.cc
#include <iostream>
#include <string>
#include <unistd.h>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
void Usage(const std::string& str)
{
std::cout << "\\n\\tUsage: " << str << " serverip serverport" << std::endl;
}
// ./tcpclient serverip serverport
int main(int argc, char* argv[])
{
if(argc != 3)
{
Usage(argv[0]);
return 0;
}
std::string serverip = argv[1];
uint16_t serverport = std::stoi(argv[2]);
struct sockaddr_in server;
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(serverport);
inet_pton(AF_INET, serverip.c_str(), &(server.sin_addr));
socklen_t len = sizeof(server);
while(true)
{
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0)
{
std::cerr << "socket create err" << std::endl;
return 1;
}
//客户端发起connect请求的时候,操作系统会自动进行端口号的随机bind绑定
int n = connect(sockfd, (struct sockaddr*)&server, len);
if(n < 0)
{
std::cerr << "connect err…" << std::endl;
return 2;
}
std::string message;
char inbuffer[4096];
std::cout << "Please Enter# ";
std::getline(std::cin, message);
n = write(sockfd, message.c_str(), message.size());
if(n < 0)
std::cerr << "write err" << std::endl;
n = read(sockfd, inbuffer, sizeof(inbuffer) – 1);
if(n > 0)
{
inbuffer[n] = 0;
std::cout << inbuffer << std::endl;
}
close(sockfd);
}
return 0;
}
TcpServer.hpp
void StartServer()
{
ThreadPool<Task>::GetInstance()->Start();
lg(Info, "tcpserver is running…");
for (;;)
{
struct sockaddr_in client;
socklen_t len = sizeof(client);
int sockfd = accept(listensock_, (struct sockaddr*)&client, &len);
if (sockfd < 0)
{
lg(Warning, "accept error, errno: %d, errstring: %s", errno, strerror(errno));
continue;
}
uint16_t clientport = ntohs(client.sin_port);
char clientip[32];
inet_ntop(AF_INET, &(client.sin_addr), clientip, sizeof(clientip));
lg(Info, "get a new link…, sockfd: %d, client ip: %s, client port: %d",
sockfd, clientip, clientport);
//version 3 多线程版
// ThreadData* td = new ThreadData(sockfd, clientip, clientport, this);
// pthread_t tid;
// pthread_create(&tid, nullptr, Routine, td);
//version 4 线程池版
Task t(sockfd, clientip, clientport);
ThreadPool<Task>::GetInstance()->Push(t);
}
}
测试
所以接下来我们运行服务器,线程池成功启动,服务器开始运行 
那么接下来运行客户端连接服务器,连接成功 
然后客户端开始输入数据,可以看到客户端的每次的输入都会变成一次新的连接,即客户端的每次输入都是一次短服务的过程

最后我们ctrl+c退出客户端即可,无误 
断线自动重连

#include <iostream>
#include <string>
#include <unistd.h>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
void Usage(const std::string& str)
{
std::cout << "\\n\\tUsage: " << str << " serverip serverport" << std::endl;
}
// ./tcpclient serverip serverport
int main(int argc, char* argv[])
{
if(argc != 3)
{
Usage(argv[0]);
return 0;
}
std::string serverip = argv[1];
uint16_t serverport = std::stoi(argv[2]);
struct sockaddr_in server;
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(serverport);
inet_pton(AF_INET, serverip.c_str(), &(server.sin_addr));
socklen_t len = sizeof(server);
while(true)
{
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0)
{
std::cerr << "socket create err" << std::endl;
return 1;
}
bool isreconnect = false;
int cnt = 5;
do
{
int n = connect(sockfd, (struct sockaddr*)&server, len);
if(n < 0)
{
//此时连接失败,那么进行断线自动重连
isreconnect = true;
cnt—;
sleep(2);
std::cerr << "connect error…, reconnect: " << cnt << std::endl;
}
else //这里必须有对connect的返回值 大于等于0 的else的判断
break;
}while(cnt && isreconnect);
if(cnt == 0)
{
std::cerr << "user offline…" << std::endl;
return 2;
}
//客户端发起connect请求的时候,操作系统会自动进行端口号的随机bind绑定
std::string message;
char inbuffer[4096];
std::cout << "Please Enter# ";
std::getline(std::cin, message);
int n = write(sockfd, message.c_str(), message.size());
if(n < 0)
std::cerr << "write err" << std::endl;
n = read(sockfd, inbuffer, sizeof(inbuffer) – 1);
if(n > 0)
{
inbuffer[n] = 0;
std::cout << inbuffer << std::endl;
}
close(sockfd);
}
return 0;
}
测试


英汉翻译
apple: 苹果
banana: 香蕉
cat: 猫
dog: 狗
egg: 鸡蛋
fish: 鱼
girl: 女孩
boy: 男孩
book: 书
pen: 钢笔
pencil: 铅笔
bag: 书包
school: 学校
teacher: 老师
student: 学生
friend: 朋友
mother: 妈妈
father: 爸爸
sister: 姐妹
brother: 兄弟
grandma: 奶奶;外婆
grandpa: 爷爷;外公
family: 家庭
home: 家
room: 房间
bed: 床
table: 桌子
chair: 椅子
door: 门
window: 窗户
blackboard: 黑板
white: 白色
black: 黑色
red: 红色
blue: 蓝色
green: 绿色
yellow: 黄色
pink: 粉色
orange: 橙色;橙子
purple: 紫色
one: 一
two: 二
three: 三
four: 四
five: 五
six: 六
seven: 七
eight: 八
nine: 九
ten: 十
eleven: 十一
twelve: 十二
thirteen: 十三
fourteen: 十四
fifteen: 十五
sixteen: 十六
seventeen: 十七
eighteen: 十八
nineteen: 十九
twenty: 二十
thirty: 三十
forty: 四十
fifty: 五十
sixty: 六十
seventy: 七十
eighty: 八十
ninety: 九十
one hundred: 一百
big: 大的
small: 小的
long: 长的
short: 短的;矮的
tall: 高的
fat: 胖的
thin: 瘦的
happy: 开心的
sad: 难过的
good: 好的
bad: 坏的
new: 新的
old: 旧的;老的
hot: 热的
cold: 冷的
warm: 温暖的
cool: 凉爽的
nice: 美好的
good morning: 早上好
good afternoon: 下午好
good evening: 晚上好
good night: 晚安
hello: 你好
hi: 嗨
bye: 再见
goodbye: 再见
thank you: 谢谢你
sorry: 对不起
please: 请
yes: 是
no: 不
ok: 好的
this: 这个
that: 那个
these: 这些
those: 那些
my: 我的
your: 你的;你们的
his: 他的
her: 她的
it: 它
is: 是
am: 是
are: 是
was: 是(过去式)
were: 是(过去式)
have: 有
has: 有(第三人称单数)
had: 有(过去式)
do: 做;助动词
does: 做;助动词(第三人称单数)
did: 做;助动词(过去式)
go: 去
come: 来
see: 看见
look: 看
watch: 观看
read: 读
write: 写
draw: 画
sing: 唱
dance: 跳舞
run: 跑
jump: 跳
walk: 走
eat: 吃
drink: 喝
sleep: 睡觉
play: 玩
toy: 玩具
ball: 球
car: 汽车
bus: 公交车
bike: 自行车
plane: 飞机
train: 火车
ship: 船
sun: 太阳
moon: 月亮
star: 星星
sky: 天空
cloud: 云
rain: 雨;下雨
snow: 雪;下雪
wind: 风
tree: 树
flower: 花
grass: 草
bird: 鸟
rabbit: 兔子
tiger: 老虎
lion: 狮子
panda: 熊猫
elephant: 大象
monkey: 猴子
pig: 猪
cow: 牛
sheep: 羊
horse: 马
day: 天;日
week: 周
month: 月
year: 年
Monday: 星期一
Tuesday: 星期二
Wednesday: 星期三
Thursday: 星期四
Friday: 星期五
Saturday: 星期六
Sunday: 星期日
January: 一月
February: 二月
March: 三月
April: 四月
May: 五月
June: 六月
July: 七月
August: 八月
September: 九月
October: 十月
November: 十一月
December: 十二月
breakfast: 早餐
lunch: 午餐
dinner: 晚餐
water: 水
milk: 牛奶
rice: 米饭
bread: 面包
meat: 肉
vegetable: 蔬菜
fruit: 水果
#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include <unistd.h>
#include "Log.hpp"
const std::string dictname = "./dict.txt";
const std::string sep = ":";
class Init
{
public:
Init()
{
std::ifstream in(dictname);
if(!in.is_open())
{
lg(Fatal, "ifstream open %s error", dictname.c_str());
exit(1);
}
std::string line;
while(std::getline(in, line))
{
std::string part1, part2;
if(Split(line, &part1, &part2))
dict.insert({ part1, part2 });
}
in.close();
}
bool Split(const std::string line, std::string* part1, std::string* part2)
{
size_t pos = line.find(sep);
if(pos == std::string::npos)
return false;
*part1 = line.substr(0, pos);
*part2 = line.substr(pos + 1);
return true;
}
std::string Translation(const std::string& key)
{
auto iter = dict.find(key);
if(iter == dict.end())
return "unknow";
return iter->second;
}
private:
std::unordered_map<std::string, std::string> dict;
};
#pragma once
#include <iostream>
#include <string>
#include <cstring>
#include <unistd.h>
#include "Log.hpp"
#include "Init.hpp"
extern Log lg;
Init init;
class Task
{
public:
Task()
{}
Task(int sockfd, const std::string& clientip, const uint16_t& clientport)
: sockfd_(sockfd)
, clientip_(clientip)
, clientport_(clientport)
{}
void operator()()
{
char inbuffer[4096];
ssize_t n = read(sockfd_, inbuffer, sizeof(inbuffer) – 1);
if (n > 0)
{
inbuffer[n] = 0;
std::cout << "client say# " << inbuffer << std::endl;
std::string echo_string = init.Translation(inbuffer);
// std::string echo_string = "tcpserver echo# ";
// echo_string += inbuffer;
n = write(sockfd_, echo_string.c_str(), echo_string.size());
if(n < 0)
lg(Info, "write err, errno: %d, errstr: %s", errno, strerror(errno));
}
else if(n == 0)
{
lg(Info, "%s:%d quit, server colse sockfd: %d", clientip_.c_str(), clientport_, sockfd_);
}
else
{
//异常
lg(Warning, "read error, sockfd: %d, client ip: %s, client port: %d",
sockfd_, clientip_.c_str(), clientport_);
}
close(sockfd_);
}
~Task()
{}
private:
int sockfd_;
std::string clientip_;
uint16_t clientport_;
};
测试
那么接下来我们编译一下代码,然后运行即可,先运行服务器 
然后运行客户端 
接下来就可以在客户端输入英语单词,然后服务器中线程池的线程拿到英语单词之后,就会进行查找拿到汉语并返回,所以客户端就可以接收到汉语并打印了,无误 
二、源代码
TcpServer.hpp
#include <iostream>
#include <string>
#include <cstring>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include "Log.hpp"
#include "ThreadPool.hpp"
#include "Task.hpp"
const int defaultfd = –1;
const uint16_t defaultport = 8080;
const std::string defaultip = "0.0.0.0";
const int backlog = 10;
extern Log lg;
enum
{
UsageError = 1,
SocketError,
BindError,
ListenError
};
// class TcpServer;
//
// class ThreadData
// {
// public:
// ThreadData(int fd, const std::string& ip, const uint16_t& p, TcpServer* t)
// : sockfd(fd)
// , clientip(ip)
// , clientport(p)
// , tsvr(t)
// {}
// public:
// int sockfd;
// std::string clientip;
// uint16_t clientport;
// TcpServer* tsvr;
// };
class TcpServer
{
public:
TcpServer(const uint16_t &port = defaultport, const std::string &ip = defaultip)
: listensock_(defaultfd), port_(port), ip_(ip)
{}
void InitServer()
{
listensock_ = socket(AF_INET, SOCK_STREAM, 0);
if (listensock_ < 0)
{
lg(Fatal, "create socket error, errno: %d, errstring: %s", errno, strerror(errno));
exit(SocketError);
}
lg(Info, "create socket success, listensock_: %d", listensock_);
//防止偶发性服务器无法立即重启
int opt = 1;
setsockopt(listensock_, SOL_SOCKET, SO_REUSEADDR|SO_REUSEPORT, &opt, sizeof(opt));
struct sockaddr_in server;
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(port_);
inet_aton(ip_.c_str(), &(server.sin_addr));
socklen_t len = sizeof(server);
if (bind(listensock_, (struct sockaddr *)&server, len) < 0)
{
lg(Fatal, "bind error, errno: %d, errstring: %s", errno, strerror(errno));
exit(BindError);
}
lg(Info, "bind socket success, listensock_: %d", listensock_);
if (listen(listensock_, backlog) < 0)
{
lg(Fatal, "listen error, errno: %d, errstring: %s", errno, strerror(errno));
exit(ListenError);
}
lg(Info, "listen socket success, listensock_: %d", listensock_);
}
// static void* Routine(void* args)
// {
// pthread_detach(pthread_self());
// ThreadData* td = static_cast<ThreadData*>(args);
// td->tsvr->Service(td->sockfd, td->clientip, td->clientport);
// close(td->sockfd);
// delete td;
// return nullptr;
// }
void StartServer()
{
ThreadPool<Task>::GetInstance()->Start();
lg(Info, "tcpserver is running…");
for (;;)
{
struct sockaddr_in client;
socklen_t len = sizeof(client);
int sockfd = accept(listensock_, (struct sockaddr*)&client, &len);
if (sockfd < 0)
{
lg(Warning, "accept error, errno: %d, errstring: %s", errno, strerror(errno));
continue;
}
uint16_t clientport = ntohs(client.sin_port);
char clientip[32];
inet_ntop(AF_INET, &(client.sin_addr), clientip, sizeof(clientip));
lg(Info, "get a new link…, sockfd: %d, client ip: %s, client port: %d",
sockfd, clientip, clientport);
//version 1 单进程/单线程版
// Service(sockfd, clientip, clientport);
// close(sockfd);
//version 2 多进程版
// pid_t id = fork();
// if(id == 0)
// {
// //child
// close(listensock_);
// if(fork() > 0)
// exit(0);
// //grandchild
// Service(sockfd, clientip, clientport);
// close(sockfd);
// exit(0);
// }
// close(sockfd);
// pid_t rid = waitpid(id, nullptr, 0);
// if(rid == id)
// std::cout << "father wait success" << std::endl;
//version 3 多线程版
// ThreadData* td = new ThreadData(sockfd, clientip, clientport, this);
// pthread_t tid;
// pthread_create(&tid, nullptr, Routine, td);
//version 4 线程池版
Task t(sockfd, clientip, clientport);
ThreadPool<Task>::GetInstance()->Push(t);
}
}
// void Service(int sockfd, const std::string& clientip, const uint16_t& clientport)
// {
// while (true)
// {
// char inbuffer[4096];
// ssize_t n = read(sockfd, inbuffer, sizeof(inbuffer) – 1);
// if (n > 0)
// {
// inbuffer[n] = 0;
// std::cout << "client say# " << inbuffer << std::endl;
// std::string echo_string = "tcpserver echo# ";
// echo_string += inbuffer;
// write(sockfd, echo_string.c_str(), echo_string.size());
// }
// else if(n == 0)
// {
// lg(Info, "%s:%d quit, server colse sockfd: %d", clientip.c_str(), clientport, sockfd);
// break;
// }
// else
// {
// //异常
// lg(Warning, "read error, sockfd: %d, client ip: %s, client port: %d",
// sockfd, clientip.c_str(), clientport);
// break;
// }
// }
// }
~TcpServer()
{
if (listensock_ > 0)
close(listensock_);
}
private:
int listensock_;
uint16_t port_;
std::string ip_;
};
Main.cc
#include <iostream>
#include <memory>
#include "TcpServer.hpp"
void Usage(const std::string str)
{
std::cout << "\\n\\tUsage: " << str << " port[1024+]\\n" << std::endl;
}
int main(int argc, char* argv[])
{
if(argc != 2)
{
Usage(argv[0]);
exit(UsageError);
}
uint16_t port = std::stoi(argv[1]);
std::unique_ptr<TcpServer> server(new TcpServer(port));
server->InitServer();
server->StartServer();
return 0;
}
TcpClient.cc
#include <iostream>
#include <string>
#include <unistd.h>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
void Usage(const std::string& str)
{
std::cout << "\\n\\tUsage: " << str << " serverip serverport" << std::endl;
}
// ./tcpclient serverip serverport
int main(int argc, char* argv[])
{
if(argc != 3)
{
Usage(argv[0]);
return 0;
}
std::string serverip = argv[1];
uint16_t serverport = std::stoi(argv[2]);
struct sockaddr_in server;
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(serverport);
inet_pton(AF_INET, serverip.c_str(), &(server.sin_addr));
socklen_t len = sizeof(server);
while(true)
{
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0)
{
std::cerr << "socket create err" << std::endl;
return 1;
}
bool isreconnect = false;
int cnt = 5;
do
{
int n = connect(sockfd, (struct sockaddr*)&server, len);
if(n < 0)
{
//此时连接失败,那么进行断线自动重连
isreconnect = true;
cnt—;
sleep(2);
std::cerr << "connect error…, reconnect: " << cnt << std::endl;
}
else
break;
}while(cnt && isreconnect);
if(cnt == 0)
{
std::cerr << "user offline…" << std::endl;
return 2;
}
//客户端发起connect请求的时候,操作系统会自动进行端口号的随机bind绑定
std::string message;
char inbuffer[4096];
std::cout << "Please Enter# ";
std::getline(std::cin, message);
int n = write(sockfd, message.c_str(), message.size());
if(n < 0)
std::cerr << "write err" << std::endl;
n = read(sockfd, inbuffer, sizeof(inbuffer) – 1);
if(n > 0)
{
inbuffer[n] = 0;
std::cout << inbuffer << std::endl;
}
close(sockfd);
}
// std::string message;
// char inbuffer[4096];
//
// while(true)
// {
// std::cout << "Please Enter# ";
// std::getline(std::cin, message);
// int n = write(sockfd, message.c_str(), message.size());
// if(n < 0)
// {
// std::cerr << "write err" << std::endl;
// break;
// }
// n = read(sockfd, inbuffer, sizeof(inbuffer) – 1);
// if(n > 0)
// {
// inbuffer[n] = 0;
// std::cout << inbuffer << std::endl;
// }
// else
// {
// break;
// }
// }
//
// close(sockfd);
return 0;
}
Tash.hpp
#pragma once
#include <iostream>
#include <string>
#include <cstring>
#include <unistd.h>
#include "Log.hpp"
#include "Init.hpp"
extern Log lg;
Init init;
class Task
{
public:
Task()
{}
Task(int sockfd, const std::string& clientip, const uint16_t& clientport)
: sockfd_(sockfd)
, clientip_(clientip)
, clientport_(clientport)
{}
void operator()()
{
char inbuffer[4096];
ssize_t n = read(sockfd_, inbuffer, sizeof(inbuffer) – 1);
if (n > 0)
{
inbuffer[n] = 0;
std::cout << "client say# " << inbuffer << std::endl;
std::string echo_string = init.Translation(inbuffer);
// std::string echo_string = "tcpserver echo# ";
// echo_string += inbuffer;
n = write(sockfd_, echo_string.c_str(), echo_string.size());
if(n < 0)
lg(Info, "write err, errno: %d, errstr: %s", errno, strerror(errno));
}
else if(n == 0)
{
lg(Info, "%s:%d quit, server colse sockfd: %d", clientip_.c_str(), clientport_, sockfd_);
}
else
{
//异常
lg(Warning, "read error, sockfd: %d, client ip: %s, client port: %d",
sockfd_, clientip_.c_str(), clientport_);
}
close(sockfd_);
}
~Task()
{}
private:
int sockfd_;
std::string clientip_;
uint16_t clientport_;
};
Init.hpp
#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include <unistd.h>
#include "Log.hpp"
const std::string dictname = "./dict.txt";
const std::string sep = ":";
class Init
{
public:
Init()
{
std::ifstream in(dictname);
if(!in.is_open())
{
lg(Fatal, "ifstream open %s error", dictname.c_str());
exit(1);
}
std::string line;
while(std::getline(in, line))
{
std::string part1, part2;
if(Split(line, &part1, &part2))
dict.insert({ part1, part2 });
}
in.close();
}
bool Split(const std::string line, std::string* part1, std::string* part2)
{
size_t pos = line.find(sep);
if(pos == std::string::npos)
return false;
*part1 = line.substr(0, pos);
*part2 = line.substr(pos + 1);
return true;
}
std::string Translation(const std::string& key)
{
auto iter = dict.find(key);
if(iter == dict.end())
return "unknow";
return iter->second;
}
private:
std::unordered_map<std::string, std::string> dict;
};
ThreadPool.hpp
#pragma once
#include <iostream>
#include <queue>
#include <vector>
#include <string>
#include <pthread.h>
static int defaultnum = 5;
struct ThreadInfo
{
pthread_t tid;
std::string threadname;
};
template<class T>
class ThreadPool
{
private:
void Lock()
{
pthread_mutex_lock(&mutex_);
}
void Unlock()
{
pthread_mutex_unlock(&mutex_);
}
void WakeUp()
{
pthread_cond_signal(&cond_);
}
void ThreadSleep()
{
pthread_cond_wait(&cond_, &mutex_);
}
bool IsQueueEmpty()
{
return tasks_.empty();
}
std::string GetThreadName(pthread_t tid)
{
for(auto& ti : threads_)
{
if(ti.tid == tid)
return ti.threadname;
}
return "None";
}
T Pop()
{
T out = tasks_.front();
tasks_.pop();
return out;
}
static void* HandlerTask(void* args)
{
ThreadPool* tp = static_cast<ThreadPool*>(args);
std::string name = tp->GetThreadName(pthread_self());
while(true)
{
tp->Lock();
while(tp->IsQueueEmpty())
{
tp->ThreadSleep();
}
T t = tp->Pop();
tp->Unlock();
t();
// std::cout << name << " run" << ", result: " << t.GetResult() << std::endl;
}
return nullptr;
}
public:
void Start()
{
int n = threads_.size();
for(int i = 0; i < n; i++)
{
threads_[i].threadname = "thread-" + std::to_string(i + 1);
pthread_create(&(threads_[i].tid), nullptr, HandlerTask, (void*)this);
}
}
void Push(const T& in)
{
Lock();
tasks_.push(in);
WakeUp();
Unlock();
}
static ThreadPool<T>* GetInstance()
{
if(tp_ == nullptr)
{
pthread_mutex_lock(&lock_);
if(tp_ == nullptr)
{
std::cout << "log: singleton create done first" << std::endl;
tp_ = new ThreadPool<T>();
}
pthread_mutex_unlock(&lock_);
}
return tp_;
}
private:
ThreadPool(int num = defaultnum):threads_(num)
{
pthread_mutex_init(&mutex_, nullptr);
pthread_cond_init(&cond_, nullptr);
}
ThreadPool(const ThreadPool<T>& ) = delete;
const ThreadPool<T>& operator=(const ThreadPool<T>& ) = delete;
~ThreadPool()
{
pthread_mutex_destroy(&mutex_);
pthread_cond_destroy(&cond_);
}
private:
std::queue<T> tasks_;
std::vector<ThreadInfo> threads_;
pthread_mutex_t mutex_;
pthread_cond_t cond_;
static ThreadPool<T>* tp_;
static pthread_mutex_t lock_;
};
template<class T>
ThreadPool<T>* ThreadPool<T>::tp_ = nullptr;
template<class T>
pthread_mutex_t ThreadPool<T>::lock_ = PTHREAD_MUTEX_INITIALIZER;
Log.hpp
#pragma once
#include <iostream>
#include <string>
#include <ctime>
#include <cstdio>
#include <cstdarg>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define SIZE 1024
#define Info 0
#define Debug 1
#define Warning 2
#define Error 3
#define Fatal 4
#define Screen 1 //输出到屏幕上
#define Onefile 2 //输出到一个文件中
#define Classfile 3 //根据事件等级输出到不同的文件中
#define LogFile "log.txt" //日志名称
class Log
{
public:
Log()
{
printMethod = Screen;
path = "./log/";
}
void Enable(int method) //改变日志打印方式
{
printMethod = method;
}
~Log()
{}
std::string levelToString(int level)
{
switch(level)
{
case Info:
return "Info";
case Debug:
return "Debug";
case Warning:
return "Warning";
case Error:
return "Error";
case Fatal:
return "Fata";
default:
return "";
}
}
void operator()(int level, const char* format, ...)
{
//默认部分 = 日志等级 + 日志时间
time_t t = time(nullptr);
struct tm* ctime = localtime(&t);
char leftbuffer[SIZE];
snprintf(leftbuffer, sizeof(leftbuffer), "[%s][%d-%d-%d %d:%d:%d]", levelToString(level).c_str(),
ctime->tm_year + 1900, ctime->tm_mon + 1, ctime->tm_mday,
ctime->tm_hour, ctime->tm_min, ctime->tm_sec);
va_list s;
va_start(s, format);
char rightbuffer[SIZE];
vsnprintf(rightbuffer, sizeof(rightbuffer), format, s);
va_end(s);
char logtxt[2 * SIZE];
snprintf(logtxt, sizeof(logtxt), "%s %s", leftbuffer, rightbuffer);
printLog(level, logtxt);
}
void printLog(int level, const std::string& logtxt)
{
switch(printMethod)
{
case Screen:
std::cout << logtxt << std::endl;
break;
case Onefile:
printOneFile(LogFile, logtxt);
break;
case Classfile:
printClassFile(level, logtxt);
break;
default:
break;
}
}
void printOneFile(const std::string& logname, const std::string& logtxt)
{
std::string _logname = path + logname;
int fd = open(_logname.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0666);
if(fd < 0)
return;
write(fd, logtxt.c_str(), logtxt.size());
close(fd);
}
void printClassFile(int level, const std::string& logtxt)
{
std::string filename = LogFile;
filename += ".";
filename += levelToString(level);
printOneFile(filename, logtxt);
}
private:
int printMethod;
std::string path;
};
Log lg;
makefile
all:tcpserver tcpclient
tcpserver:Main.cc
g++ –o $@ $^ –std=c++11 –lpthread
tcpclient:TcpClient.cc
g++ –o $@ $^ –std=c++11
.PHONT:clean
clean:
rm –f tcpserver tcpclient
dict.txt
apple: 苹果
banana: 香蕉
cat: 猫
dog: 狗
egg: 鸡蛋
fish: 鱼
girl: 女孩
boy: 男孩
book: 书
pen: 钢笔
pencil: 铅笔
bag: 书包
school: 学校
teacher: 老师
student: 学生
friend: 朋友
mother: 妈妈
father: 爸爸
sister: 姐妹
brother: 兄弟
grandma: 奶奶;外婆
grandpa: 爷爷;外公
family: 家庭
home: 家
room: 房间
bed: 床
table: 桌子
chair: 椅子
door: 门
window: 窗户
blackboard: 黑板
white: 白色
black: 黑色
red: 红色
blue: 蓝色
green: 绿色
yellow: 黄色
pink: 粉色
orange: 橙色;橙子
purple: 紫色
one: 一
two: 二
three: 三
four: 四
five: 五
six: 六
seven: 七
eight: 八
nine: 九
ten: 十
eleven: 十一
twelve: 十二
thirteen: 十三
fourteen: 十四
fifteen: 十五
sixteen: 十六
seventeen: 十七
eighteen: 十八
nineteen: 十九
twenty: 二十
thirty: 三十
forty: 四十
fifty: 五十
sixty: 六十
seventy: 七十
eighty: 八十
ninety: 九十
one hundred: 一百
big: 大的
small: 小的
long: 长的
short: 短的;矮的
tall: 高的
fat: 胖的
thin: 瘦的
happy: 开心的
sad: 难过的
good: 好的
bad: 坏的
new: 新的
old: 旧的;老的
hot: 热的
cold: 冷的
warm: 温暖的
cool: 凉爽的
nice: 美好的
good morning: 早上好
good afternoon: 下午好
good evening: 晚上好
good night: 晚安
hello: 你好
hi: 嗨
bye: 再见
goodbye: 再见
thank you: 谢谢你
sorry: 对不起
please: 请
yes: 是
no: 不
ok: 好的
this: 这个
that: 那个
these: 这些
those: 那些
my: 我的
your: 你的;你们的
his: 他的
her: 她的
it: 它
is: 是
am: 是
are: 是
was: 是(过去式)
were: 是(过去式)
have: 有
has: 有(第三人称单数)
had: 有(过去式)
do: 做;助动词
does: 做;助动词(第三人称单数)
did: 做;助动词(过去式)
go: 去
come: 来
see: 看见
look: 看
watch: 观看
read: 读
write: 写
draw: 画
sing: 唱
dance: 跳舞
run: 跑
jump: 跳
walk: 走
eat: 吃
drink: 喝
sleep: 睡觉
play: 玩
toy: 玩具
ball: 球
car: 汽车
bus: 公交车
bike: 自行车
plane: 飞机
train: 火车
ship: 船
sun: 太阳
moon: 月亮
star: 星星
sky: 天空
cloud: 云
rain: 雨;下雨
snow: 雪;下雪
wind: 风
tree: 树
flower: 花
grass: 草
bird: 鸟
rabbit: 兔子
tiger: 老虎
lion: 狮子
panda: 熊猫
elephant: 大象
monkey: 猴子
pig: 猪
cow: 牛
sheep: 羊
horse: 马
day: 天;日
week: 周
month: 月
year: 年
Monday: 星期一
Tuesday: 星期二
Wednesday: 星期三
Thursday: 星期四
Friday: 星期五
Saturday: 星期六
Sunday: 星期日
January: 一月
February: 二月
March: 三月
April: 四月
May: 五月
June: 六月
July: 七月
August: 八月
September: 九月
October: 十月
November: 十一月
December: 十二月
breakfast: 早餐
lunch: 午餐
dinner: 晚餐
water: 水
milk: 牛奶
rice: 米饭
bread: 面包
meat: 肉
vegetable: 蔬菜
fruit: 水果
总结
以上就是今天的博客内容啦,希望对读者朋友们有帮助 水滴石穿,坚持就是胜利,读者朋友们可以点个关注 点赞收藏加关注,找到小编不迷路!





