代码拉取完成,页面将自动刷新
#include <iostream>
#include <string>
#include <cerrno>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include "Log.hpp"
#include <assert.h>
#include <signal.h>
#include <sys/wait.h>
#include "Thread.hpp"
#include <vector>
#include <memory>
#include "ThreadPool.hpp"
#include "Task.hpp"
#define NUM 1024
static void service(int service_sockfd, std::string client_ip, uint16_t client_port, const std::string &name)
{
char buffer[NUM]; // 以字符串作为缓冲区
while (1)
{
// 读取缓冲区内容
ssize_t s = read(service_sockfd, buffer, sizeof(buffer) - 1);
if (s > 0) // 读取成功
{
buffer[s] = '\0'; // 标记数据的末尾
std::cout << name << ": "; // 显示线程编号
std::cout << "IP[" << client_ip << "], PORT[" << client_port << "]: " << buffer << std::endl;
}
else if (s == 0) // 无数据
{
logMessage(NORMAL, "%s: IP[%s], PORT[%u] shut down...me too", name.c_str(), client_ip.c_str(), client_port);
break;
}
else // 读取失败
{
logMessage(ERROR, "read socket error...%d:%s", errno, strerror(errno));
break;
}
// 写入数据
write(service_sockfd, buffer, strlen(buffer));
}
close(service_sockfd);
}
class TcpServer
{
public:
// 线程函数
static void *routine(void *args)
{
ThreadData *tdata = static_cast<ThreadData *>(args);
service(tdata->_sockfd, tdata->_ip, tdata->_port, tdata->_name);
pthread_detach(pthread_self());
delete tdata;
return nullptr;
}
private:
const static int _backlog = 20;
public:
TcpServer(uint16_t port, std::string ip = "")
: _port(port)
, _ip(ip)
, _listen_sockfd(-1)
, _threadpool_ptr(ThreadPool<Task>::getThreadPool())
{}
~TcpServer()
{
if (_listen_sockfd >= 0)
close(_listen_sockfd);
}
bool initServer()
{
// 1. 创建套接字
_listen_sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (_listen_sockfd < 0)
{
logMessage(FATAL, "%d:%s", errno, strerror(errno));
exit(2);
}
logMessage(DEBUG, "%s: %d", "create socket success, sockfd", _listen_sockfd);
// 2. 绑定
// 2.1 填充属性
struct sockaddr_in local;
memset(&local, 0, sizeof(local));
local.sin_family = AF_INET; // 网络传输
local.sin_port = htons(_port); // 本地->网络
local.sin_addr.s_addr = _ip.empty() ? INADDR_ANY : inet_addr(_ip.c_str());
// 2.2 绑定
if (bind(_listen_sockfd, (struct sockaddr *)&local, sizeof(local)) < 0)
{
logMessage(FATAL, "bind():errno:%d:%s", errno, strerror(errno));
exit(3);
}
// 3. 监听
if (listen(_listen_sockfd, _backlog) < 0)
{
logMessage(FATAL, "listen()errno:%d:%s", errno, strerror(errno));
exit(4);
}
logMessage(NORMAL, "initialize tdp server...%s", strerror(errno));
return true;
}
void start()
{
_threadpool_ptr->run(); // 线程池执行任务
while (1)
{
// 4.1 获取链接
struct sockaddr_in client;
memset(&client, 0, sizeof(client));
socklen_t len = sizeof(client);
int service_sockfd = accept(_listen_sockfd, (struct sockaddr *)&client, &len);
// 获取连接失败
if (service_sockfd < 0)
{
logMessage(ERROR, "accept()errno:%d:%s", errno, strerror(errno));
continue; // 继续
}
// 获取连接成功
// 通信准备 (网络->主机)
uint16_t client_port = ntohs(client.sin_port);
std::string client_ip = inet_ntoa(client.sin_addr);
logMessage(NORMAL, "link success, IP[%s], PORT[%u], server sock: %d\n",
client_ip.c_str(), client_port, service_sockfd);
// 线程池版本
Task task(service_sockfd, client_ip, client_port, service); // 生产任务
_threadpool_ptr->pushTask(task); // push任务
}
}
private:
int _listen_sockfd; // 监听套接字
int16_t _port; // 端口号
std::string _ip; // IP地址
std::unique_ptr<ThreadPool<Task>> _threadpool_ptr; // 指向线程池对象的地址
};
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。