127 lines
3.7 KiB
C++
127 lines
3.7 KiB
C++
|
|
#include <uv.h>
|
||
|
|
#include <iostream>
|
||
|
|
#include <vector>
|
||
|
|
#include <cstdlib>
|
||
|
|
#include <cstring>
|
||
|
|
#include <thread>
|
||
|
|
#include <mutex>
|
||
|
|
#include <chrono>
|
||
|
|
#include <iomanip>
|
||
|
|
#include <sstream>
|
||
|
|
|
||
|
|
#define container_of(ptr, type, member) \
|
||
|
|
((type *)((char *)(ptr) - offsetof(type, member)))
|
||
|
|
|
||
|
|
const int MAX_CONNECTIONS = 300;
|
||
|
|
const int MAX_MESSAGE_SIZE = 1024 * 1024; // 1MB
|
||
|
|
|
||
|
|
struct Client {
|
||
|
|
uv_tcp_t handle;
|
||
|
|
uv_connect_t connect_req;
|
||
|
|
uv_write_t write_req;
|
||
|
|
std::string server_ip;
|
||
|
|
int server_port;
|
||
|
|
bool connected;
|
||
|
|
std::mutex mutex;
|
||
|
|
};
|
||
|
|
|
||
|
|
std::vector<Client*> clients;
|
||
|
|
uv_loop_t* loop;
|
||
|
|
|
||
|
|
void on_write(uv_write_t* req, int status) {
|
||
|
|
Client* client = container_of(req, Client, write_req);
|
||
|
|
if (status < 0) {
|
||
|
|
std::cerr << "Write error: " << uv_strerror(status) << std::endl;
|
||
|
|
uv_close((uv_handle_t*)&client->handle, nullptr);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void on_read(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) {
|
||
|
|
Client* client = container_of(stream, Client, handle);
|
||
|
|
if (nread < 0) {
|
||
|
|
std::cerr << "Read error: " << uv_strerror(nread) << std::endl;
|
||
|
|
uv_close((uv_handle_t*)&client->handle, nullptr);
|
||
|
|
free(buf->base);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (nread > 0) {
|
||
|
|
std::cout << "Received " << nread << " bytes from server" << std::endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
free(buf->base);
|
||
|
|
}
|
||
|
|
|
||
|
|
void on_connect(uv_connect_t* req, int status) {
|
||
|
|
Client* client = container_of(req, Client, connect_req);
|
||
|
|
if (status < 0) {
|
||
|
|
std::cerr << "Connect error: " << uv_strerror(status) << std::endl;
|
||
|
|
uv_close((uv_handle_t*)&client->handle, nullptr);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
client->connected = true;
|
||
|
|
std::cout << "Connected to server: " << client->server_ip << ":" << client->server_port << std::endl;
|
||
|
|
|
||
|
|
// Get the client's IP and port
|
||
|
|
struct sockaddr_in addr;
|
||
|
|
int addr_len = sizeof(addr);
|
||
|
|
uv_tcp_getpeername(&client->handle, (struct sockaddr*)&addr, &addr_len);
|
||
|
|
|
||
|
|
char client_ip[INET_ADDRSTRLEN];
|
||
|
|
uv_ip4_name((const struct sockaddr_in*)&addr, client_ip, INET_ADDRSTRLEN);
|
||
|
|
int client_port = ntohs(addr.sin_port);
|
||
|
|
|
||
|
|
// Prepare message with client's IP and port
|
||
|
|
std::stringstream ss;
|
||
|
|
ss << "Client IP: " << client_ip << ", Port: " << client_port;
|
||
|
|
std::string message = ss.str();
|
||
|
|
|
||
|
|
// Send the message
|
||
|
|
uv_buf_t buf_list = uv_buf_init(const_cast<char*>(message.c_str()), message.size());
|
||
|
|
uv_write(&client->write_req, (uv_stream_t*)&client->handle, &buf_list, 1, on_write);
|
||
|
|
|
||
|
|
uv_read_start((uv_stream_t*)&client->handle, [](uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) {
|
||
|
|
buf->base = (char*)malloc(suggested_size);
|
||
|
|
buf->len = suggested_size;
|
||
|
|
}, on_read);
|
||
|
|
}
|
||
|
|
|
||
|
|
void start_client(Client* client) {
|
||
|
|
struct sockaddr_in addr;
|
||
|
|
uv_ip4_addr(client->server_ip.c_str(), client->server_port, &addr);
|
||
|
|
|
||
|
|
uv_tcp_init(loop, &client->handle);
|
||
|
|
uv_tcp_connect(&client->connect_req, &client->handle, (const struct sockaddr*)&addr, on_connect);
|
||
|
|
}
|
||
|
|
|
||
|
|
void run_client_thread(Client* client) {
|
||
|
|
start_client(client);
|
||
|
|
uv_run(loop, UV_RUN_DEFAULT);
|
||
|
|
}
|
||
|
|
|
||
|
|
int main2() {
|
||
|
|
loop = uv_default_loop();
|
||
|
|
|
||
|
|
// Create and start 300 clients
|
||
|
|
for (int i = 0; i < MAX_CONNECTIONS; ++i) {
|
||
|
|
Client* client = new Client;
|
||
|
|
client->server_ip = "172.22.128.1"; // Replace with your server IP
|
||
|
|
client->server_port = 8098; // Replace with your server port
|
||
|
|
client->connected = false;
|
||
|
|
|
||
|
|
std::thread client_thread(run_client_thread, client);
|
||
|
|
client_thread.detach();
|
||
|
|
|
||
|
|
clients.push_back(client);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Handle shutdown or other logic here
|
||
|
|
while (true) {
|
||
|
|
// You can add logic to handle client connections, messages, etc.
|
||
|
|
// For example, sending data periodically or handling disconnects.
|
||
|
|
uv_run(loop, UV_RUN_ONCE);
|
||
|
|
}
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|