• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Dziwna sytuacja z winsock | C++

Object Storage Arubacloud
0 głosów
337 wizyt
pytanie zadane 19 maja 2018 w C i C++ przez Mamrotek Nowicjusz (180 p.)
edycja 20 maja 2018 przez Mamrotek

Witam forumowiczów,

od kilku dni zmagam się (pewnie jak się okaże - banalnym) problemem z biblioteką winsock2.h.

Otóż serwer ciągle zwraca błąd, mimo poprawnego połączenia się i nie wyświetla mojej wiadomości. Co więcej, przy sztucznym wywołaniu błędu w kodzie serwera okazało się, że ten ciągle "słucha" i wywala ten błąd gdy otrzymuje wiadomość (oczywiście kod podaję bez improwizowanego błędu).

Oto moje wypociny. Proszę nie zwracać uwagi na gdzieniegdzie brak kontroli błędów i ogólny bałagan w kodzie. Napisałem tylko, żeby zobaczyć, czy to w ogóle działa.

//Server

#define  _WINSOCK_DEPRECATED_NO_WARNINGS

#include <Winsock2.h>
#include <iostream>

#define DEFAULT_PORT 12018
#define HIDE_CONSOLE_WINDOW true

int main()
{
    int iResult;
    //Winsock Startup
    WSAData wsaData;
    WORD DllVersion = MAKEWORD(2, 1);
    if (WSAStartup(DllVersion, &wsaData) != 0)
    {
        MessageBoxA(NULL, "Winsock startup failed!", "ERROR", MB_OK | MB_ICONERROR);
        exit(1);
    }

    SOCKADDR_IN addr;
    int addrlen = sizeof(addr);
    addr.sin_addr.s_addr =  inet_addr("192.168.100.2");
    addr.sin_port = htons(DEFAULT_PORT);
    addr.sin_family = AF_INET;
    memset( &( addr.sin_zero ), '\0', 8 );

    SOCKET sListen = socket(AF_INET, SOCK_STREAM, NULL);
    bind(sListen, (SOCKADDR*)&addr, sizeof(addr));
    listen(sListen, SOMAXCONN);

    SOCKET newConnection;

    newConnection = accept(sListen, (SOCKADDR*)&addr, &addrlen);
    if (newConnection == 0)
    {
        std::cout << "Failed to accept the client's connection" << std::endl;
    }

    char recBuf[256] = "";
        do
        {
            iResult = recv(sListen, (char*)recBuf, sizeof(recBuf), NULL);
            Sleep(100);
            std::cout<<recBuf<<std::endl;

           /* if (iResult > 0)
            {
                std::cout<<"Bytes received: "<< iResult<<std::endl;
                break;
            }
            else if (iResult == 0)
                std::cout<<"Connection closed "<< iResult<<std::endl;
           // else
             //   std::cout<<"recv failed "<< iResult<<std::endl;
             */
        }
        while (iResult==-1);

    system("pause");
    return 0;
}

 

2 odpowiedzi

0 głosów
odpowiedź 19 maja 2018 przez j23 Mędrzec (194,920 p.)
edycja 19 maja 2018 przez j23

Linia 37: accept zwraca INVALID_SOCKET w razie błędu, a nie 0.

Linia 60: recv zwraca SOCKET_ERROR w razie błędu. Nie stosuj magic numbers, bo możesz się zdziwić. Przy takim warunku pętla zostanie przerwana przy pierwszym obrocie, chyba że recv zwróci błąd. Chyba nie o to Ci chodziło?

0 głosów
odpowiedź 20 maja 2018 przez Mamrotek Nowicjusz (180 p.)

Linia 37: accept zwraca INVALID_SOCKET w razie błędu, a nie 0.

Linia 60: recv zwraca SOCKET_ERROR w razie błędu. Nie stosuj magic numbers, bo możesz się zdziwić. Przy takim warunku pętla zostanie przerwana przy pierwszym obrocie, chyba że recv zwróci błąd. Chyba nie o to Ci chodziło?

Na razie chodziło mi właśnie o to. Ponawiać pętlę, dopóki recv() zwraca błąd. Po zastosowaniu INVALID_SOCKET oraz SOCKET_ERROR sytuacja się nie zmienia.

komentarz 20 maja 2018 przez j23 Mędrzec (194,920 p.)
edycja 20 maja 2018 przez j23

Nie zaczynaj dyskusji pisząc odpowiedź, użyj komentarzy - po to one są. To po pierwsze. Po drugie, sprawdź firewalla i antywirusa, bo czasami mogą namieszać  Pokaż też, jak wysyłasz wiadomość.

Popraw jeszcze jedną rzecz:

iResult = recv(sListen, (char*)recBuf, sizeof(recBuf) - 1, 0);
if(iResult > 0)
{
        recBuf[iResult] = '\0';
        std::cout << recBuf << '\n';
}
komentarz 20 maja 2018 przez Mamrotek Nowicjusz (180 p.)
Nie korzystam z antywirusa, ani firewall'a. Nowy kod nic nie pomógł.
komentarz 20 maja 2018 przez Mamrotek Nowicjusz (180 p.)

@j23, Może to w kodzie klienta jest błąd?

if(send(Connection, msg.c_str(), 512, NULL)<0)
{
std::cout<<"Error";
}
else std::cout<<"Success";

 

komentarz 20 maja 2018 przez j23 Mędrzec (194,920 p.)
if(send(Connection, msg.c_str(), msg.size(), 0) < 0)
...

 

komentarz 20 maja 2018 przez Mamrotek Nowicjusz (180 p.)
Na jedno wychodzi.
komentarz 20 maja 2018 przez Mamrotek Nowicjusz (180 p.)
Dziękuję Ci za pomoc. Problem rozwiązałem już sam. Otóż okazało się, że do funkcji recv() powinienem podać deskryptor gniazda otrzymany przy wywołaniu accept().

Pozdrawiam forum. Błąd był prosty, ale może ktoś tu trafi i nie będzie musiał dłubać tyle co ja.

Podobne pytania

+2 głosów
2 odpowiedzi 2,955 wizyt
pytanie zadane 26 kwietnia 2015 w C i C++ przez achilles147 Dyskutant (9,580 p.)
0 głosów
0 odpowiedzi 367 wizyt
0 głosów
1 odpowiedź 156 wizyt
pytanie zadane 12 lutego 2018 w C i C++ przez Hiskiel Pasjonat (22,830 p.)

92,576 zapytań

141,426 odpowiedzi

319,652 komentarzy

61,961 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...