Networking Initial

This commit is contained in:
IlushaShurupov 2023-07-16 20:03:14 +03:00 committed by Ilya Shurupov
parent d5dfb1c304
commit 038e6c58cf
6 changed files with 178 additions and 86 deletions

View file

@ -1,54 +1,56 @@
#include <asio.hpp>
#include <cstring>
#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <list>
#include <mutex>
#include <pthread.h>
class Server {
struct SharedData {
std::list<asio::ip::tcp::socket*> clients;
std::mutex mutex;
};
SharedData mSharedData;
//int serverSocket;
int port;
public:
Server(int port) : serverSocket(-1), port(port) {}
Server(int port) : port(port) {}
~Server() { assert(0); }
bool start() {
// Create socket
serverSocket = socket(AF_INET, SOCK_STREAM, 0);
if (serverSocket == -1) {
std::cerr << "Failed to create socket" << std::endl;
return false;
}
asio::io_context io_context;
asio::ip::tcp::acceptor serverSocket(io_context);
// Bind socket to port
sockaddr_in serverAddress{};
serverAddress.sin_family = AF_INET;
serverAddress.sin_port = htons(port);
serverAddress.sin_addr.s_addr = INADDR_ANY;
if (bind(serverSocket, reinterpret_cast<sockaddr*>(&serverAddress), sizeof(serverAddress)) == -1) {
std::cerr << "Failed to bind socket" << std::endl;
return false;
}
serverSocket.open(asio::ip::tcp::v4());
// serverSocket.set_option(asio::ip::tcp::acceptor::reuse_address(true));
serverSocket.bind(asio::ip::tcp::endpoint(asio::ip::tcp::v4(), port));
// Listen for connections
if (listen(serverSocket, 5) == -1) {
std::cerr << "Failed to listen on socket" << std::endl;
return false;
}
serverSocket.listen();
std::cout << "Server listening on port " << port << std::endl;
// Start accepting clients
while (true) {
// Accept client connection
sockaddr_in clientAddress{};
socklen_t clientAddressSize = sizeof(clientAddress);
int clientSocket = accept(serverSocket, reinterpret_cast<sockaddr*>(&clientAddress), &clientAddressSize);
if (clientSocket == -1) {
std::cerr << "Failed to accept client connection" << std::endl;
return false;
}
auto clientSocket = new asio::ip::tcp::socket(io_context);
serverSocket.accept(*clientSocket);
// add client
mSharedData.mutex.lock();
mSharedData.clients.push_back(clientSocket);
mSharedData.mutex.unlock();
// Create a new thread to handle the client
pthread_t threadId;
if (pthread_create(&threadId, nullptr, handleClient, &clientSocket) != 0) {
if (pthread_create(&threadId, nullptr, handleClient, this) != 0) {
std::cerr << "Failed to create thread for client" << std::endl;
return false;
}
@ -58,40 +60,81 @@ public:
}
// Close server socket
close(serverSocket);
serverSocket.close();
return true;
}
private:
int serverSocket;
int port;
static void* handleClient(void* clientSocketPtr) {
int clientSocket = *(reinterpret_cast<int*>(clientSocketPtr));
constexpr int BUFFER_SIZE = 1024;
static void* handleClient(void* in) {
auto self = (Server*) in;
// Receive and print client message
char buffer[BUFFER_SIZE];
ssize_t bytesRead = read(clientSocket, buffer, BUFFER_SIZE - 1);
if (bytesRead == -1) {
std::cerr << "Failed to read from socket" << std::endl;
return nullptr;
// read shared data - current client id
self->mSharedData.mutex.lock();
auto clientSocket = self->mSharedData.clients.back();
self->mSharedData.mutex.unlock();
MESSAGE:
// wait for a message request1
short messageSize;
{
auto bytesRead = asio::read(*clientSocket, asio::buffer(&messageSize, 2));
if (bytesRead == -1) {
std::cerr << "Failed to read from socket" << std::endl;
(*clientSocket).close();
return nullptr;
}
}
buffer[bytesRead] = '\0';
std::cout << "Received message from client: " << buffer << std::endl;
self->mSharedData.mutex.lock();
// Receive client message
auto message = new char[messageSize + 1];
message[messageSize] = '\0';
{
auto bytesRead = asio::read(*clientSocket, asio::buffer(message, messageSize));
if (bytesRead == -1) {
std::cerr << "Failed to read from socket" << std::endl;
memcpy(message, "Cant wanna say something but i cant read", 100);
}
}
// Broadcast to all clients
for (auto client: self->mSharedData.clients) {
auto bytesWritten = asio::write(*client, asio::buffer(&messageSize, 2));
if (bytesWritten == -1) {
std::cerr << "Failed to write to socket" << std::endl;
}
bytesWritten = write(*client, asio::buffer(message, messageSize));
if (bytesWritten == -1) {
std::cerr << "Failed to write to socket" << std::endl;
}
}
auto exit = memcmp(message, "exit", strlen("exit")) == 0;
// Close socket
close(clientSocket);
delete[] message;
return nullptr;
if (exit) {
(*clientSocket).close();
self->mSharedData.clients.remove(clientSocket);
}
self->mSharedData.mutex.unlock();
if (exit) {
return nullptr;
}
goto MESSAGE;
}
};
int main() {
Server server(8080);
Server server(3333);
server.start();
return 0;
}
}