Pull to refresh

Comments 3

Жуть какая.

  1. Что мешало сделать отдельные методы int network_init(); и void network_done(); Что бы единообразно в разных ос инициализировать сеть.

  2. addrinfo* GetServerLocalAddress() возвращает не адрес а создаёт список адресов, которые еще потом надо не забыть освободить с помощью freeaddrinfo. Это в рамках C++ не в какие ворота.

  3. А если у нас адрес в ipv6?

  4. Вместо switch лучше сгородить dispatcher сообщений

  5. нет обработки сигналов

  6. А если вдруг понадобиться заменить канал на защищенный ssl или использовать прокси то всё опять переписывать?

  7. Сами с json не стали связываться использовали готовую либу. Так что мешало и для сети поступить так же?

В общем вместо того что бы скрыть недостатки posix и винды вы наружу выворачиваете. Весь common.h можно было оставить в реализации и не заставлять компилятор елозить по системным хидерам, а выкатить только интерфейс для работы клиента и сервера без инклюдов винды и posix.

Note, however, select() is becoming obsolete for modern network applications and C++20 coroutines are growing more popular

Как это вообще с C++20 связано, вместо select есть epoll. И если надо coroutines можно в обычно C организовать даже на старых компиляторах как stack-less так и stack-full. В C++20 просто появился дополнительный механизм для реализации.

Итого: Для простого примера слишком сложно, а до образцовой реализации слишком далеко.

Спасибо большое за Ваши замечания. Я всё ещё учусь и хотел написать эту статью таким же новичкам, как и я. Конечно, у меня есть ошибки, ведь я сам ещё ученик, просто который изучает это некоторое время :)
Обязательно учту все неточности и прочитаю про новые темы!

Creating your own messaging protocol and implementing socket communication in C++ involves several steps. Below, I'll provide a basic example of how you can achieve this. This example will cover a simple client-server architecture using TCP sockets.

Server Side (Messaging Protocol and Socket Handling)

#include
#include
#include <sys/socket.h>
#include <netinet/in.h>

const int PORT = 8080;

// Define your messaging protocol
struct Message {
int type; // You can define different message types
char data[1024]; // Actual message data
};

int main() {
// Create socket
int serverSocket = socket(AF_INET, SOCK_STREAM, 0);
if (serverSocket == -1) {
std::cerr << "Error creating socket\n";
return -1;
}

// Bind the socket to a specific address and port
sockaddr_in serverAddr{};
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(PORT);
serverAddr.sin_addr.s_addr = INADDR_ANY;

if (bind(serverSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == -1) {
    std::cerr << "Error binding socket\n";
    close(serverSocket);
    return -1;
}

// Listen for incoming connections
if (listen(serverSocket, 10) == -1) {
    std::cerr << "Error listening for connections\n";
    close(serverSocket);
    return -1;
}

std::cout << "Server listening on port " << PORT << std::endl;

// Accept connections and handle messages
while (true) {
    sockaddr_in clientAddr{};
    socklen_t clientLen = sizeof(clientAddr);
    int clientSocket = accept(serverSocket, (struct sockaddr*)&clientAddr, &clientLen);

    if (clientSocket == -1) {
        std::cerr << "Error accepting connection\n";
        continue;
    }

    std::cout << "Connection accepted from " << inet_ntoa(clientAddr.sin_addr) << std::endl;

    // Handle messages from the client
    Message receivedMessage;
    while (recv(clientSocket, &receivedMessage, sizeof(receivedMessage), 0) > 0) {
        // Process the received message
        std::cout << "Received message of type " << receivedMessage.type << ": " << receivedMessage.data << std::endl;

        // Example: Respond to the client
        Message responseMessage;
        responseMessage.type = 1;
        strcpy(responseMessage.data, "Hello, client!");
        send(clientSocket, &responseMessage, sizeof(responseMessage), 0);
    }

    close(clientSocket);
    std::cout << "Connection closed with " << inet_ntoa(clientAddr.sin_addr) << std::endl;
}

// Close the server socket
close(serverSocket);

return 0;


Creating your own messaging protocol and implementing socket communication in C++ involves several steps. Below, I'll provide a basic example of how you can achieve this. This example will cover a simple client-server architecture using TCP sockets.

Server Side (Messaging Protocol and Socket Handling)
cpp
Copy code
#include <iostream>
#include <cstring>
#include <sys/socket.h>
#include <netinet/in.h>

const int PORT = 8080;

// Define your messaging protocol
struct Message {
    int type; // You can define different message types
    char data[1024]; // Actual message data
};

int main() {
    // Create socket
    int serverSocket = socket(AF_INET, SOCK_STREAM, 0);
    if (serverSocket == -1) {
        std::cerr << "Error creating socket\n";
        return -1;
    }

    // Bind the socket to a specific address and port
    sockaddr_in serverAddr{};
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(PORT);
    serverAddr.sin_addr.s_addr = INADDR_ANY;

    if (bind(serverSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == -1) {
        std::cerr << "Error binding socket\n";
        close(serverSocket);
        return -1;
    }

    // Listen for incoming connections
    if (listen(serverSocket, 10) == -1) {
        std::cerr << "Error listening for connections\n";
        close(serverSocket);
        return -1;
    }

    std::cout << "Server listening on port " << PORT << std::endl;

    // Accept connections and handle messages
    while (true) {
        sockaddr_in clientAddr{};
        socklen_t clientLen = sizeof(clientAddr);
        int clientSocket = accept(serverSocket, (struct sockaddr*)&clientAddr, &clientLen);

        if (clientSocket == -1) {
            std::cerr << "Error accepting connection\n";
            continue;
        }

        std::cout << "Connection accepted from " << inet_ntoa(clientAddr.sin_addr) << std::endl;

        // Handle messages from the client
        Message receivedMessage;
        while (recv(clientSocket, &receivedMessage, sizeof(receivedMessage), 0) > 0) {
            // Process the received message
            std::cout << "Received message of type " << receivedMessage.type << ": " << receivedMessage.data << std::endl;

            // Example: Respond to the client
            Message responseMessage;
            responseMessage.type = 1;
            strcpy(responseMessage.data, "Hello, client!");
            send(clientSocket, &responseMessage, sizeof(responseMessage), 0);
        }

        close(clientSocket);
        std::cout << "Connection closed with " << inet_ntoa(clientAddr.sin_addr) << std::endl;
    }

    // Close the server socket
    close(serverSocket);

    return 0;
}
Clien

Clients Side

#include
#include
#include <sys/socket.h>
#include <netinet/in.h>

const int PORT = 8080;

int main() {
// Create socket
int clientSocket = socket(AF_INET, SOCK_STREAM, 0);
if (clientSocket == -1) {
std::cerr << "Error creating socket\n";
return -1;
}

// Connect to the server
sockaddr_in serverAddr{};
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(PORT);
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");

if (connect(clientSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == -1) {
    std::cerr << "Error connecting to server\n";
    close(clientSocket);
    return -1;
}

std::cout << "Connected to server\n";

// Send messages to the server
while (true) {
    // Example: Send a message of type 1
    char messageData[1024];
    std::cout << "Enter a message: ";
    std::cin.getline(messageData, sizeof(messageData));

    Message sendMessage;
    sendMessage.type = 1;
    strcpy(sendMessage.data, messageData);

    send(clientSocket, &sendMessage, sizeof(sendMessage), 0);

    // Receive and process the server's response
    Message receivedMessage;
    recv(clientSocket, &receivedMessage, sizeof(receivedMessage), 0);

    std::cout << "Server response of type " << receivedMessage.type << ": " << receivedMessage.data << std::endl;
}

// Close the client socket
close(clientSocket);

return 0;

}

This is a basic example, and in a real-world scenario, you might need to handle error cases more robustly, implement additional security measures, and consider more advanced messaging protocols depending on your application's requirements. Additionally, consider using libraries like Boost.Asio for more advanced and efficient network programming in C++.

Sign up to leave a comment.

Articles