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

Dziwna sytuacja z winsock | C++

VPS Starter Arubacloud
0 głosów
319 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,897 wizyt
pytanie zadane 26 kwietnia 2015 w C i C++ przez achilles147 Dyskutant (9,580 p.)
0 głosów
0 odpowiedzi 345 wizyt
0 głosów
1 odpowiedź 153 wizyt
pytanie zadane 12 lutego 2018 w C i C++ przez Hiskiel Pasjonat (22,830 p.)

92,454 zapytań

141,263 odpowiedzi

319,099 komentarzy

61,854 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

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 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!

...