Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.

Winsock recv problem

[es] :: C/C++ programiranje :: Winsock recv problem

[ Pregleda: 2247 | Odgovora: 4 ] > FB > Twit

Postavi temu Odgovori

Autor

Pretraga teme: Traži
Markiranje Štampanje RSS

_Punisher_

Član broj: 43956
Poruke: 95
194.106.174.*

Sajt: www.raznocafe.com


Profil

icon Winsock recv problem19.08.2006. u 14:14 - pre 214 meseci
Imam sledeci kod,a moji je problem sto treba ceo odgvor iz socka da stavim u jedan string kako bi to dalje parsirao.
Code:

#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>


#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "80"

int __cdecl main(int argc, char **argv) 
{
    int recvbuflen = DEFAULT_BUFLEN;
    WSADATA wsaData;
    
    SOCKET ConnectSocket = INVALID_SOCKET;
    struct addrinfo *result = NULL,
                    *ptr = NULL,
                    hints;
    char *sendbuf = "GET / HTTP/1.1\r\nHost: www.google.com\r\nConnection: Close\r\n\r\n";
    char *recvbuf;
    char *html;

    
    int iResult;
    
    
    // Validate the parameters
    if (argc != 2) {
        printf("usage: %s server-name\n", argv[0]);
        return 1;
    }

    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (iResult != 0) {
        printf("WSAStartup failed: %d\n", iResult);
        return 1;
    }

    ZeroMemory( &hints, sizeof(hints) );
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    // Resolve the server address and port
    iResult = getaddrinfo(argv[1], DEFAULT_PORT, &hints, &result);
    if ( iResult != 0 ) {
        printf("getaddrinfo failed: %d\n", iResult);
        WSACleanup();
        return 1;
    }

    // Attempt to connect to an address until one succeeds
    for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {

        // Create a SOCKET for connecting to server
        ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, 
            ptr->ai_protocol);
        if (ConnectSocket == INVALID_SOCKET) {
            printf("Error at socket(): %ld\n", WSAGetLastError());
            freeaddrinfo(result);
            WSACleanup();
            return 1;
        }

        // Connect to server.
        iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
        if (iResult == SOCKET_ERROR) {
            closesocket(ConnectSocket);
            ConnectSocket = INVALID_SOCKET;
            continue;
        }
        break;
    }

    freeaddrinfo(result);

    if (ConnectSocket == INVALID_SOCKET) {
        printf("Unable to connect to server!\n");
        WSACleanup();
        return 1;
    }

    // Send an initial buffer
    iResult = send( ConnectSocket, sendbuf, (int)strlen(sendbuf), 0 );
    if (iResult == SOCKET_ERROR) {
        printf("send failed: %d\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
    }

    printf("Bytes Sent: %ld\n", iResult);

    // shutdown the connection since no more data will be sent
    iResult = shutdown(ConnectSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) {
        printf("shutdown failed: %d\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
    }

    // Receive until the peer closes the connection
    do {

        iResult = recv(ConnectSocket, recvbuf, (int)strlen(recvbuf), 0);
        
        if ( iResult > 0 ){

//OVO MI NE RADI
strcat(html,recvbuf);
            
        }
        else if ( iResult == 0 ){
            printf("Connection closed\n");
        
        }
        else
            printf("recv failed: %d\n", WSAGetLastError());

    } while( iResult > 0 );
    
printf(html);

    
    


    
    // cleanup
    closesocket(ConnectSocket);
    WSACleanup();
    
    return 0;
}


Uvek kadapokrenem gore program dobijem error memmory could not be read.

Ono konkretno sto meni treba je kako da ceo respons od socketa stavim u varijablu html.
Hvala
:: Vas online cafe:: http://www.raznocafe.com
 
Odgovor na temu

nikoladsp
nikola radovanovic
trenutno-developer
novi sad

Član broj: 5455
Poruke: 193
*.ns.ac.yu.



Profil

icon Re: Winsock recv problem21.08.2006. u 07:00 - pre 214 meseci
ne radi ti jer nisi alocirao memoriju za html, vec imas neinicijalizovan pointer...
Code:
char html[8192]
ili da alociras dinamicki sa
Code:
char* html = new char[8192]

savet:ono sto je bitno je ti bafer bude dovoljno veliki za ono sto ces dobiti sa socketa,mislim da je 8192 sasvim ok,pogotovo za tcp(kod tebe je nesto manji). praksa je da imas neki dinamicki bafer sa realokacijom u koji 'utrpavas' ono sto ti stize sa soketa a onda to parsiras (iz nekog drugog thread-a) i brises iz bafera ono sto si isparsirao. ako ti zatreba takav bafer,postovacu ti primer jedne jednostavne klase. mogao bi da proveris i dali su ti parametri za kreiranje socketa dobri. potrazi 'beej guide to network programming' na netu i procitaj.fantasticno je covek sve opisao.

pozdrav.
ja sam panker sa diplomom kod moje mame...
 
Odgovor na temu

yooyo

Član broj: 4891
Poruke: 1101
*.dip0.t-ipconnect.de.



Profil

icon Re: Winsock recv problem21.08.2006. u 14:43 - pre 214 meseci
recv nece primiti ceo paket.. nego samo delic...
Potrebno je da vise puta pozivas recv i da prispele bajtove slazes u neki buffer pa tek tada da parsiras. recv vraca broj primljenih bajtova. Ako je taj broj majni od duzine poruke, pozivaj recv sve dok cela poruka ne stigne.

Isto vazi i za send... ako je buffer malo veci.. ne znaci da ce ga celog poslati... treba da saljes u komadicima.. tj.. send ce da vrati broj poslatih bajtova i ako je taj broj manji od duzine buffera pozovi send sa ostatkom buffera.

 
Odgovor na temu

X Files
Vladimir Stefanovic
Pozarevac

SuperModerator
Član broj: 15100
Poruke: 4901
*.static.po.sbb.co.yu.

Jabber: xfiles@elitesecurity.org


+638 Profil

icon Re: Winsock recv problem21.08.2006. u 17:40 - pre 214 meseci
Citat:

recv nece primiti ceo paket.. nego samo delic...

Da, ovo je kljucno. Teoretski, moze se desiti da se u jednom send/receive, posalje/primi
celih 8000+ bajtova, ali to *nije* zagarantovano. Najgori slucaj je kada tako uradjen
program proradi u 'laboratorisjkim' uslovima, a u realnim 'puca'. Primetio sam da i u Examples
kod Borlanda postoji takav nakaradan primer, koji moze samo da dovede u zabludu one
koji pocinju sa socket programiranjem.

Citat:

Potrebno je da vise puta pozivas recv i da prispele bajtove slazes u neki buffer pa tek tada
da parsiras. recv vraca broj primljenih bajtova. Ako je taj broj majni od duzine poruke, pozivaj
recv sve dok cela poruka ne stigne.

Isto vazi i za send... ako je buffer malo veci.. ne znaci da ce ga celog poslati... treba da
saljes u komadicima.. tj.. send ce da vrati broj poslatih bajtova i ako je taj broj manji od
duzine buffera pozovi send sa ostatkom buffera.

Jedino sto bih dodao ovom lepom objasnjenju, je da potencijalni broj recv-ova ne mora
nuzno da odgovara broju send-ova.

Dalje, mogu da postoje dva 'koncepta' slanja koliko sam uspeo da vidim da se koriste:

1) pokusas da posaljes ceo buffer (ma koliki bio), pa zatim na osnovu povratne vrednosti
vidis odakle drugi put da nastavis.

2) uvek saljes u bufferima konstantne velicine, npr 2000, ali ipak opet moras da gledas
da li je sve poslato ili nije.

Resenje broj 1 je gotovo uvek efikasnije (manji broj slanja), mada ponekad postoje razlozi
i za 2, ali se vise ne secam objasnjenja.

Takodje, treba smisliti kako server obavestiti o duzini (kraju) poruke koju treba da primi, tj.
kada da se formira (spoji) konacna poruka od niza buffera primljenih u recv. Nekada je to
trivijalno ako se radi o cistom text-based ASCII-ju, a nekada kada se prenose binarni
podaci, moze se iskoristiti 'trik' da se prvo u send posalje velicina poruke, koja se na
recv strani odmah primi i ceka da ostatak poruke dostigne tu duzinu.

PSEUDO /odavno ne koristim nativna resenja pa se i ne secam sintakse/:

--- Client ---

int ukupna_duzina = NEKA_VELICINA_U_BAJTOVIMA;
int koliko_je_poslato = SEND ( &ukupna_duzina, sizeof(int) );
// ...

--- Server ---
int ocekivana_duzina = 0;
int koliko_je_stiglo = READ ( &ocekivana_duzina, sizeof(int) );
// ...


itd...

Sigurno na netu ima gotovih primera za ovo. Inace, kada jednom odradis genericke
funkcije za slanje/primanje, vise nikada neces imati problema sa time...
 
Odgovor na temu

Sarevok

Član broj: 80738
Poruke: 10
195.252.79.*



Profil

icon Re: Winsock recv problem21.08.2006. u 19:10 - pre 214 meseci
Citat:
Da, ovo je kljucno. Teoretski, moze se desiti da se u jednom send/receive, posalje/primi
celih 8000+ bajtova, ali to *nije* zagarantovano. Najgori slucaj je kada tako uradjen
program proradi u 'laboratorisjkim' uslovima, a u realnim 'puca'. Primetio sam da i u Examples
kod Borlanda postoji takav nakaradan primer, koji moze samo da dovede u zabludu one
koji pocinju sa socket programiranjem.


Slican je sluchaj sa gomilom funkcija u C-u.
Na primer kada citam tudji kod vrlo cesto vidim da ljudi ne proveravaju broj vracenih bajtova funkcije fwrite(), iako funkcija ne garantuje da ce zapisati onoliko koliko se trazi. Takav kod uglavnom radi ispravno, jer su retke situacije da pisanje ne uspe, ali zato kada ne uspe onda nastaje pakao ;)
Slicno vazi i za fread() i gomilu drugih funkcija.
 
Odgovor na temu

[es] :: C/C++ programiranje :: Winsock recv problem

[ Pregleda: 2247 | Odgovora: 4 ] > FB > Twit

Postavi temu Odgovori

Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.