RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 953237
Accepted
Юрій Писанка
Юрій Писанка
Asked:2020-03-07 00:06:21 +0000 UTC2020-03-07 00:06:21 +0000 UTC 2020-03-07 00:06:21 +0000 UTC

C++ 局域网数据交换

  • 772

情况:我正在用 C++ 实现一个用于管理本地网络上的计算机的程序。


问题:如何从客户端发送数据结构并在服务器程序上接收。请举个例子。也许有一个专门的图书馆,类似于curl互联网。
解决方案:事实证明,全球网络和本地网络并没有我想象的那么不同。对于解决方案,我将使用我自己的 C++ HTTP 服务器,您可以curl从浏览器访问它。

这是我在同一站点上找到并修改的服务器代码。程序接收到一个请求并从 index.html 文件中返回文本,如果它不存在,它会发送一个文件不存在的消息。感谢所有为这个问题做出贡献的人。

#include <iostream>
#include <sstream>
#include <string>
#include <fstream>

// Для корректной работы freeaddrinfo в MinGW
// Подробнее: http://stackoverflow.com/a/20306451
#define _WIN32_WINNT 0x501

#include <WinSock2.h>
#include <WS2tcpip.h>

// Необходимо, чтобы линковка происходила с DLL-библиотекой
// Для работы с сокетам
#pragma comment(lib, "Ws2_32.lib")

using std::cerr;

//Получить один из ІР первый попавшыйся
std::string GetIP()
{
std::string out = "WinSock ERR";
WSADATA wsaData;
if (!WSAStartup(WINSOCK_VERSION, &wsaData)){char chInfo[64];
if (!gethostname(chInfo, sizeof(chInfo)))
{
hostent *sh;
sh=gethostbyname((char*)&chInfo);
if (sh!=NULL)
{
int nAdapter = 0;
while (sh->h_addr_list[nAdapter])
{
struct sockaddr_in adr;
memcpy(&adr.sin_addr, sh->h_addr_list[nAdapter], sh->h_length);
out = inet_ntoa(adr.sin_addr);
nAdapter++;
}
}
}
}
WSACleanup();
return out;
}

//Получить фаил в формате строки
bool getFile(char* url,std::string &r)
{
    r = "";
    std::ifstream in(url);
            if(in)
            {
                while(1)
                {
                    char t;
                    in.get(t);
                    if(in.eof()) break;
                    r+=t;
                }
            in.close();
            }
            else
            return false;
            return true;
}

int main()
{



    //char *a = (char*)x;

    std::string sIP = GetIP();
    std::cout<<sIP<<'\n';

    WSADATA wsaData; // служебная структура для хранение информации
    // о реализации Windows Sockets
    // старт использования библиотеки сокетов процессом
    // (подгружается Ws2_32.dll)
    int result = WSAStartup(MAKEWORD(2, 2), &wsaData);

    // Если произошла ошибка подгрузки библиотеки
    if (result != 0) {
        cerr << "WSAStartup failed: " << result << "\n";
        return result;
    }

    struct addrinfo* addr = NULL; // структура, хранящая информацию
    // об IP-адресе  слущающего сокета

    // Шаблон для инициализации структуры адреса
    struct addrinfo hints;
    ZeroMemory(&hints, sizeof(hints));

    hints.ai_family = AF_INET; // AF_INET определяет, что будет
    // использоваться сеть для работы с сокетом
    hints.ai_socktype = SOCK_STREAM; // Задаем потоковый тип сокета
    hints.ai_protocol = IPPROTO_TCP; // Используем протокол TCP
    hints.ai_flags = AI_PASSIVE; // Сокет будет биндиться на адрес,
    // чтобы принимать входящие соединения

    // Инициализируем структуру, хранящую адрес сокета - addr
    // Наш HTTP-сервер будет висеть на 8000-м порту локалхоста
    result = getaddrinfo(sIP.c_str(), "80", &hints, &addr);

    // Если инициализация структуры адреса завершилась с ошибкой,
    // выведем сообщением об этом и завершим выполнение программы
    if (result != 0) {
        cerr << "getaddrinfo failed: " << result << "\n";
        WSACleanup(); // выгрузка библиотеки Ws2_32.dll
        return 1;
    }

    // Создание сокета
    int listen_socket = socket(addr->ai_family, addr->ai_socktype,
        addr->ai_protocol);
    // Если создание сокета завершилось с ошибкой, выводим сообщение,
    // освобождаем память, выделенную под структуру addr,
    // выгружаем dll-библиотеку и закрываем программу
    if (listen_socket == INVALID_SOCKET) {
        cerr << "Error at socket: " << WSAGetLastError() << "\n";
        freeaddrinfo(addr);
        WSACleanup();
        return 1;
    }



    // Привязываем сокет к IP-адресу
    result = bind(listen_socket, addr->ai_addr, (int)addr->ai_addrlen);

    // Если привязать адрес к сокету не удалось, то выводим сообщение
    // об ошибке, освобождаем память, выделенную под структуру addr.
    // и закрываем открытый сокет.
    // Выгружаем DLL-библиотеку из памяти и закрываем программу.
    if (result == SOCKET_ERROR) {
        cerr << "bind failed with error: " << WSAGetLastError() << "\n";
        freeaddrinfo(addr);
        closesocket(listen_socket);
        WSACleanup();
        return 1;
    }

    // Инициализируем слушающий сокет
    if (listen(listen_socket, SOMAXCONN) == SOCKET_ERROR) {
        cerr << "listen failed with error: " << WSAGetLastError() << "\n";
        closesocket(listen_socket);
        WSACleanup();
        return 1;
    }


    const int max_client_buffer_size = 1024;
    char buf[max_client_buffer_size];
    int client_socket = INVALID_SOCKET;

    for (;;) {
        // Принимаем входящие соединения
        client_socket = accept(listen_socket, NULL, NULL);
        if (client_socket == INVALID_SOCKET) {
            cerr << "accept failed: " << WSAGetLastError() << "\n";
            closesocket(listen_socket);
            WSACleanup();
            return 1;
        }

        result = recv(client_socket, buf, max_client_buffer_size, 0);

        std::stringstream response; // сюда будет записываться ответ клиенту
        std::stringstream response_body; // тело ответа

        if (result == SOCKET_ERROR) {
            // ошибка получения данных
            cerr << "recv failed: " << result << "\n";
            closesocket(client_socket);
        } else if (result == 0) {
            // соединение закрыто клиентом
            cerr << "connection closed...\n";
        } else if (result > 0) {
            // Мы знаем фактический размер полученных данных, поэтому ставим метку конца строки
            // В буфере запроса.
            buf[result] = '\0';

            // Данные успешно получены
            // формируем тело ответа (HTML)
         /*   response_body << "<title>Test C++ HTTP Server</title>\n"
                << "<h1>Test page</h1>\n"
                << "<p>This is body of the test page...</p>\n";*/

            std::string file;

            std::string zp = buf;
            //int Start = zp.find("GET");
            //int End = zp.find("\n",Start);
            //zp = zp.substr(Start,End);

            //int pos = zp.find("comand=shutdownS",0);

            //if(pos != std::string::npos)
            //std::cout<<pos<<std::endl;

            std::cout<<'\n'<<zp<<'\n';

            if(getFile("index.html",file))
            {       
                    response_body<<file;
            }
            else
            {
                response_body << "<title>Test C++ HTTP Server</title>\n"
                << "<h1>No file index.html</h1>\n"
                << "<p>This is body of the test page...</p>\n";
            }


               /* << "<h2>Request headers</h2>\n"
                << "<pre>" << buf << "</pre>\n"
                << "<em><small>Test C++ Http Server</small></em>\n";*/

            // Формируем весь ответ вместе с заголовками
            response << "HTTP/1.1 200 OK\r\n"
                << "Version: HTTP/1.1\r\n"
                << "Content-Type: text/html; charset=utf-8\r\n"
                << "Content-Length: " << response_body.str().length()
                << "\r\n\r\n"
                << response_body.str();

            // Отправляем ответ клиенту с помощью функции send
            result = send(client_socket, response.str().c_str(),
                response.str().length(), 0);

            if (result == SOCKET_ERROR) {
                // произошла ошибка при отправле данных
                cerr << "send failed: " << WSAGetLastError() << "\n";
            }
            // Закрываем соединение к клиентом
            closesocket(client_socket);
        }
    }

    // Убираем за собой
    closesocket(listen_socket);
    freeaddrinfo(addr);
    WSACleanup();
    return 0;
}


当我试图找出代码时,我总是删除不必要的检查,因为这里是没有检查的代码

#include <iostream>
    #include <sstream>
    #include <string>
    #include <fstream>

    // Для корректной работы freeaddrinfo в MinGW
    // Подробнее: http://stackoverflow.com/a/20306451
    #define _WIN32_WINNT 0x501

    #include <WinSock2.h>
    #include <WS2tcpip.h>

    // Необходимо, чтобы линковка происходила с DLL-библиотекой
    // Для работы с сокетам
    #pragma comment(lib, "Ws2_32.lib")

    using std::cerr;

    //Получить один из ІР первый попавшыйся
    std::string GetIP()
    {
    std::string out = "WinSock ERR";
    WSADATA wsaData;
    if (!WSAStartup(WINSOCK_VERSION, &wsaData)){char chInfo[64];
    if (!gethostname(chInfo, sizeof(chInfo)))
    {
    hostent *sh;
    sh=gethostbyname((char*)&chInfo);
    if (sh!=NULL)
    {
    int nAdapter = 0;
    while (sh->h_addr_list[nAdapter])
    {
    struct sockaddr_in adr;
    memcpy(&adr.sin_addr, sh->h_addr_list[nAdapter], sh->h_length);
    out = inet_ntoa(adr.sin_addr);
    nAdapter++;
    }
    }
    }
    }
    WSACleanup();
    return out;
    }


    int main()
    {



        //char *a = (char*)x;

        std::string sIP = GetIP();
        std::cout<<sIP<<'\n';

        WSADATA wsaData; // служебная структура для хранение информации
        // о реализации Windows Sockets
        // старт использования библиотеки сокетов процессом
        // (подгружается Ws2_32.dll)
        int result = WSAStartup(MAKEWORD(2, 2), &wsaData);


        struct addrinfo* addr = NULL; // структура, хранящая информацию
        // об IP-адресе  слущающего сокета

        // Шаблон для инициализации структуры адреса
        struct addrinfo hints;
        ZeroMemory(&hints, sizeof(hints));

        hints.ai_family = AF_INET; // AF_INET определяет, что будет
        // использоваться сеть для работы с сокетом
        hints.ai_socktype = SOCK_STREAM; // Задаем потоковый тип сокета
        hints.ai_protocol = IPPROTO_TCP; // Используем протокол TCP
        hints.ai_flags = AI_PASSIVE; // Сокет будет биндиться на адрес,
        // чтобы принимать входящие соединения

        // Инициализируем структуру, хранящую адрес сокета - addr
        // Наш HTTP-сервер будет висеть на 8000-м порту локалхоста
        result = getaddrinfo(sIP.c_str(), "80", &hints, &addr);

        // Создание сокета
        int listen_socket = socket(addr->ai_family, addr->ai_socktype,
            addr->ai_protocol);
        // Если создание сокета завершилось с ошибкой, выводим сообщение,
        // освобождаем память, выделенную под структуру addr,
        // выгружаем dll-библиотеку и закрываем программу


        // Привязываем сокет к IP-адресу
        result = bind(listen_socket, addr->ai_addr, (int)addr->ai_addrlen);



        // Инициализируем слушающий сокет
        listen(listen_socket, SOMAXCONN);



        const int max_client_buffer_size = 1024;
        char buf[max_client_buffer_size];
        int client_socket = INVALID_SOCKET;

        for (;;) {
            // Принимаем входящие соединения
            client_socket = accept(listen_socket, NULL, NULL);


            result = recv(client_socket, buf, max_client_buffer_size, 0);

            std::stringstream response; // сюда будет записываться ответ клиенту
            std::stringstream response_body; // тело ответа

 if (result > 0) {
                // Мы знаем фактический размер полученных данных, поэтому ставим метку конца строки
                // В буфере запроса.
                buf[result] = '\0';

                std::string file;

                std::string zp = buf;

                std::cout<<'\n'<<zp<<'\n';

                //напечатать ответ
                    response_body << "<title>Test C++ HTTP Server</title>\n"
                    << "<h1>Hello server C++</h1>\n"
                    << "<p>This is body of the test page...</p>\n";




                // Формируем весь ответ вместе с заголовками
                response << "HTTP/1.1 200 OK\r\n"
                    << "Version: HTTP/1.1\r\n"
                    << "Content-Type: text/html; charset=utf-8\r\n"
                    << "Content-Length: " << response_body.str().length()
                    << "\r\n\r\n"
                    << response_body.str();

                // Отправляем ответ клиенту с помощью функции send
                result = send(client_socket, response.str().c_str(),
                    response.str().length(), 0);

                // Закрываем соединение к клиентом
                closesocket(client_socket);
            }
        }

        // Убираем за собой
        closesocket(listen_socket);
        freeaddrinfo(addr);
        WSACleanup();
        return 0;
    }

程序在启动时会在控制台中显示 IP 地址,必须在浏览器中输入该地址。如果您在本地网络上并且程序获取网络连接的适配器的地址,无论是 Wi-Fi 还是有线,本地网络上的任何计算机都可以发送请求并接收响应从你的程序。有个不知道怎么修复的bug,有时候页面加载时间长,没有收到响应,但是如果重新加载,响应立马就来了。

c++
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    calm27
    2020-03-07T01:53:59Z2020-03-07T01:53:59Z

    您可以使用网络C++库组件中最流行的网络选项之一。boost

    另外,在这里,如果由于某种原因它不起作用,您一定可以找到合适的库来解决您的问题boost。

    • 2

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    根据浏览器窗口的大小调整背景图案的大小

    • 2 个回答
  • Marko Smith

    理解for循环的执行逻辑

    • 1 个回答
  • Marko Smith

    复制动态数组时出错(C++)

    • 1 个回答
  • Marko Smith

    Or and If,elif,else 构造[重复]

    • 1 个回答
  • Marko Smith

    如何构建支持 x64 的 APK

    • 1 个回答
  • Marko Smith

    如何使按钮的输入宽度?

    • 2 个回答
  • Marko Smith

    如何显示对象变量的名称?

    • 3 个回答
  • Marko Smith

    如何循环一个函数?

    • 1 个回答
  • Marko Smith

    LOWORD 宏有什么作用?

    • 2 个回答
  • Marko Smith

    从字符串的开头删除直到并包括一个字符

    • 2 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5