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

pitanja u vezi funkcije recv (WinSocket)

[es] :: C/C++ programiranje :: pitanja u vezi funkcije recv (WinSocket)

Strane: 1 2

[ Pregleda: 3091 | Odgovora: 21 ] > FB > Twit

Postavi temu Odgovori

Autor

Pretraga teme: Traži
Markiranje Štampanje RSS

Shejn
Srbija

Član broj: 11830
Poruke: 232
*.dynamic.sbb.rs.



Profil

icon pitanja u vezi funkcije recv (WinSocket)20.10.2010. u 10:25 - pre 149 meseci
Dobar dan.

Dva pitanja,
1. da li je moguce da neki karakter koji stize 'zatvori' recv kanal .. \n ili \r\n?

2. ima li potrebe setovati velicinu recv buffera ?
setsockopt(s_socket, SOL_SOCKET, SO_RCVBUF, (char *)&rcvSockBufsize, (int)sizeof(rcvSockBufsize));?
 
Odgovor na temu

Mihajlo Cvetanović
Beograd

Moderator
Član broj: 37636
Poruke: 1239



+94 Profil

icon Re: pitanja u vezi funkcije recv (WinSocket)20.10.2010. u 10:42 - pre 149 meseci
1. Ne znam na šta tačno misliš pod zatvaranjem kanala, ali u socket streamu nema specijalnih karaktera, tako da je odgovor "ne", šta god da je bilo pitanje.

2. Veličinu bafera ne treba dirati, nego treba tako raditi sa soketom da je veličina bafera nebitna. To znači da ako imaš mali broj soketa (ili samo jedan) onda u večitoj petlji radiš select-recv (nemoj dva recv jedan za drugim). Ako imaš mnogo soketa (to jest praviš heavy duty server) onda je bolje da napustiš recv i radiš sa I/O completion portovima. Jeste prilično komplikovano, ali postoji s razlogom.
 
Odgovor na temu

X Files
Vladimir Stefanovic
Pozarevac

SuperModerator
Član broj: 15100
Poruke: 4898
212.200.65.*

Jabber: xfiles@elitesecurity.org


+637 Profil

icon Re: pitanja u vezi funkcije recv (WinSocket)20.10.2010. u 13:08 - pre 149 meseci
Citat:
1. da li je moguce da neki karakter koji stize 'zatvori' recv kanal .. \n ili \r\n?

Kao što Mihajlo reče, stream podataka koji pristiže može da bude proizvoljnog sadržaja i ne postoji nekakav kontrolni kod koji bi baš tada prekinuo konekciju. U principu, može se isprogramirati da PRIJEMNIK raskine konekciju kada dobije određeni string pattern, ali to u praksi često nije najbolje rešenje za većinu slučajeva. Možda jeste Ok rešenje ako se koristi za usko ograničene potrebe. Na sličnom principu rade recimo primitivne SendText() implementacije.

Jedan od koncepata koji se koristi pri SLANJU poruka je da se prvobitno definise DUŽINA streama:
PREDAJNIK:
SEND LENGTH(STREAM)
SEND STREAM

PRIJEMNIK:
READ LENGTH
READ STREAM(LENGTH)

E sad, dobro je poznavati prirodu TCP/IP protokola, jer to objašnjava neke razloge za prethodno definisanje (ograničavanje) stream-ova DUŽINOM:

* Jedan SEND na strani PREDAJNIKA koji je prosledio CEO želejni stream podataka, može da proizvede više READ dogadjaja na strani PRIJEMNIKA, jer mreža nije mogla da isporuči odjednom sve podatke
* Jedan SEND na strani PREDAJNIKA nije uspeo da prosledi mreži CEO željeni stream podataka, pa je potrebno slanje (SEND) nastaviti od mesta prekida sve do definisane dužine. Najčešće povratna vrednost funkcije slanja govori koliko je bajtova prosleđeno u datom pokušaju.
* Više SEND-ova na strani PREDAJNIKA, mreža može spojiti i proizvesti samo jedan READ na strani PRIJEMNIKA

Ovo poslednje recimo može da proizvede sledeće: poslao si neki tekst sa CR+LF a kraju, a zatim si ubrzo poslao i drugi tekst sa CR+LF a kraju. Očekivao si da za svaki od dva SEND-a odradi po jedan READ, sa diskonekcijom između, kako si predvideo programom. Međutim, desilo se da su dva SEND-a proizvela samo jedan READ. Ti si zatim u READ pročitao tekst do prvog CR+LF (jer je tako isprogramirano), a ostatak diskonekcijom odbacio i tako izgubio!

Kada se dužinom streama definiše koliko parče podataka treba ukupno poslati/primiti, lakše je odreagovati i na greške i ponovo započeti slanje ako je potrebno.

Mislim, sve je ovo teorija, ali ovo pričam čisto da osetiš na kakve probleme i situacije možeš naići u realnom socket programiranju, jer u laboratorijskim uslovima (na jednom računaru ili rasterećenom LAN-u) najčešće sve radi, dok se ne dođe do "prave" mreže.



 
Odgovor na temu

mmix
Miljan Mitrović
Profesorkin muz
Passau, Deutschland

SuperModerator
Član broj: 17944
Poruke: 6041



+4631 Profil

icon Re: pitanja u vezi funkcije recv (WinSocket)20.10.2010. u 13:15 - pre 149 meseci
A zasto jednostavno ne oboris konekciju umesto slanja "specijalnog karaktera"?
Sloba je za 12 godina promenio antropološki kod srpskog naroda. On je od jednog naroda koji je bio veseo, pomalo površan, od jednog naroda koji je bio znatiželjan, koji je voleo da vidi, da putuje, da upozna,
od naroda koji je bio kosmopolitski napravio narod koji je namršten, mrzovoljan, sumnjicav, zaplašen, narod koji se stalno nešto žali, kome je stalno neko kriv… - Z.Đinđić
 
Odgovor na temu

Shejn
Srbija

Član broj: 11830
Poruke: 232
*.dynamic.sbb.rs.



Profil

icon Re: pitanja u vezi funkcije recv (WinSocket)20.10.2010. u 13:40 - pre 149 meseci
Hvala na odgovorima.

Da malo pojasnim problem.

Sa servera dobijam nekoliko redova podataka, npr.
red1\r\n
red2\r\n
...
redn\r\n


a ja sa recv procitam samo 1 red i to je to, desi se timout.

evo i funkcije:
Code:

void CConnection::RECEIVE_File(CString naziv_fajla, BOOL sinhro, CString *error)
{
    CString tt, str_tmp;
    int x=0, length=0, krug=0, rcvLen=190192, endBuffLen=0, pokusaj=0, socTimeout;
    SYSTEMTIME localTime;
    DWORD dw1, dw2;

    char *rcvBuff = NULL;
    rcvBuff = new char[256];
    memset(rcvBuff, '\0', rcvLen);


    HANDLE hFile = CreateFile(naziv_fajla, GENERIC_WRITE | GENERIC_READ,FILE_SHARE_READ, NULL, CREATE_ALWAYS, NULL, NULL);


    if (hFile == INVALID_HANDLE_VALUE)
    {
        CloseHandle(hFile);
        return;
    }

    socTimeout = 15;//timeout
    fd_set fdReadSet;
    FD_ZERO(&fdReadSet);
        FD_SET(s_socket, &fdReadSet);
    fdReadSet.fd_array[0] = s_socket;
    fdReadSet.fd_count = 1;
    TIMEVAL tO;

    tO.tv_sec = socTimeout;
    tO.tv_usec = 0;

    CString zz;
    int err_pokusaj = 0;
    
    while(true)
    {
        fdReadSet.fd_count = 1;
        if(select(0, &fdReadSet, NULL, NULL, &tO) == 0)
        {
            SOCKET_Close();
            SOCKET_Open();

            (*error) = _T("SOCKET TIMEOUT");
            break; //timeout
        }

        memset(rcvBuff, '\0', 256);
        x = recv(s_socket, rcvBuff, 256, 0);

        zz.Format(_T("stiglo: %d byte"), x*sizeof(char));
        AfxMessageBox(zz);

        if(x == SOCKET_ERROR)
        {
            SOCKET_Close();
            SOCKET_Open();
            
            if(err_pokusaj == 10)
            {
                (*error) = _T("SOCKET ERROR");
                break;
            }

            err_pokusaj++;
        }
        else
        {
            err_pokusaj=0;
            dw2 = x;
            WriteFile( hFile, rcvBuff, dw2, &dw1, NULL);
            zz.Format(_T("upisano u fajl:%d byte"), dw1*sizeof(char));
            AfxMessageBox(zz);
            
            if(x>6)
            {
                if( RECEIVE_End(1, rcvBuff, x) )//dogovor je da se na kraju salje odredjena kombinacija karaktera koja je duzine 7 .. i to se ovde proverava
                {
                    SOCKET_Close();
                    SOCKET_Open();

                    AfxMessageBox(_T("DETEKTOVAN KRAJ."));
                    
                    break;
                }
                memset(endBuff, '\0', 10);
            }

        }

    
    }
    AfxMessageBox(_T("KRAJ"));

    CloseHandle(hFile);
    delete[] rcvBuff;
    rcvBuff = NULL;

    return;
}


Napomena. Moguce da na serverskoj strani nije nesto dobro odradjeno ...
 
Odgovor na temu

Mihajlo Cvetanović
Beograd

Moderator
Član broj: 37636
Poruke: 1239



+94 Profil

icon Re: pitanja u vezi funkcije recv (WinSocket)20.10.2010. u 14:49 - pre 149 meseci
Možeš sa Wiresharkom tačno da vidiš šta se dešava, koji se paketi kome šalju. Na žalost Wireshark ne radi posao ako se koristi na windows računaru na kome su oba kraja konekcije. Možda ima neki drugi sniffer koji to omogućava.

Inače, ovako na prvi pogled, pozivaš select, ali ne proveravaš da li je select vratio SOCKET_ERROR. Isto tako, strukturu fdReadSet popunjavaš sa s_socket, ali samo prvi put, a ako promeniš s_socket u međuvremenu (close/open) onda vrednost u strukturi više nije validna.
 
Odgovor na temu

Shejn
Srbija

Član broj: 11830
Poruke: 232
*.dynamic.sbb.rs.



Profil

icon Re: pitanja u vezi funkcije recv (WinSocket)20.10.2010. u 15:03 - pre 149 meseci
Citat:
Mihajlo Cvetanović: Možeš sa Wiresharkom tačno da vidiš šta se dešava, koji se paketi kome šalju. Na žalost Wireshark ne radi posao ako se koristi na windows računaru na kome su oba kraja konekcije. Možda ima neki drugi sniffer koji to omogućava.

Ovo cu probati, pa cu javiti rezultate.
Citat:

Inače, ovako na prvi pogled, pozivaš select, ali ne proveravaš da li je select vratio SOCKET_ERROR. Isto tako, strukturu fdReadSet popunjavaš sa s_socket, ali samo prvi put, a ako promeniš s_socket u međuvremenu (close/open) onda vrednost u strukturi više nije validna.


funkcija je bila prvobitno uradjen da na prvi socke_error iskoci napolje .. kasnije je promenjena da zavrti koji put ali je zaboravljeno da se ponovo popuni struktura fdReadSet .. :(
hvala, promenucu i ovo pa se javim.
 
Odgovor na temu

Shejn
Srbija

Član broj: 11830
Poruke: 232
*.dynamic.sbb.rs.



Profil

icon Re: pitanja u vezi funkcije recv (WinSocket)20.10.2010. u 19:03 - pre 149 meseci
Problem nastaje kad se prima vise podatak > ~1300byte u tom slucaju se upise prvi red u fajl, onda se zakuca na recv() do timeouta, a zatim izadje iz while petlje.

U pitanju je winCE 5.0 OS.

Saljem i dve funkcije
ispravljena RECEIVE_File()
SOCKET_Open()

evo ispravljene funkcije RECEIVE_File:
Code:

void CConnection::RECEIVE_File(CString naziv_fajla, BOOL sinhro, CString *error)
{
        CString tt, str_tmp;
        int x=0, socTimeout;
        DWORD dw1, dw2;
        
        char *rcvBuff = NULL;
        rcvBuff = new char[128];
        memset(rcvBuff, '\0', 128);
        
        HANDLE hFile = CreateFile(naziv_fajla, GENERIC_WRITE | GENERIC_READ,FILE_SHARE_READ, NULL, CREATE_ALWAYS, NULL, NULL);

        if (hFile == INVALID_HANDLE_VALUE)
        {
            (*error) = _T("(RD2) GRESKA PRI KREIRANJU FAJLA.\n\rMOLIMO VAS POKUSAJTE PONOVO.");
            CloseHandle(hFile);
            return;
        }

        fd_set fdReadSet;
        FD_ZERO(&fdReadSet);
        FD_SET(s_socket, &fdReadSet);
        fdReadSet.fd_array[0] = s_socket;
        fdReadSet.fd_count = 1;
        TIMEVAL tO;
        //timeout 30 sec
        socTimeout = 30;
        
        tO.tv_sec = socTimeout;
        tO.tv_usec = 0;

        CString zz;
        int err_code = -1, err_pokusaj = 0;
        
        while(true)
        {
            FD_ZERO(&fdReadSet);
            FD_SET(s_socket, &fdReadSet);

            if ((err_code = select(0, &fdReadSet, NULL, NULL, &tO)) == SOCKET_ERROR)
            {
                SOCKET_Close();
                SOCKET_Open();

                (*error) = _T("SOCKET ERROR");
                break;

            }

            if(err_code > 0)
            {

                if (FD_ISSET(s_socket, &fdReadSet))
                {

                    memset(rcvBuff, '\0', 128);
                    x = recv(s_socket, rcvBuff, 128, 0);

                    zz.Format(_T("stiglo:%d byte"), x*sizeof(char));
                    AfxMessageBox(zz);

                    if(x == SOCKET_ERROR)
                    {
                        SOCKET_Close();
                        SOCKET_Open();

                        (*error) = _T("SOCKET ERROR");
                        break;
                    }
                    else
                    {
                        dw2 = x;
                        WriteFile( hFile, rcvBuff, dw2, &dw1, NULL);
                        zz.Format(_T("upisano u fajl:%d byte"), dw1*sizeof(char));
                        AfxMessageBox(zz);
                        
                        if(x>6) //dogovor je da se na kraju salje odredjena kombinacija karaktera koja je duzine 7 .. i to se ovde proverava
                        {
                            if( RECEIVE_End(1, rcvBuff, x) )
                            {
                                SOCKET_Close();
                                SOCKET_Open();

                                AfxMessageBox(_T("DETEKTOVAN KRAJ."));
                                
                                break;
                            }

                            memset(endBuff, '\0', 10);
                            endBuffLen = 0;
                        }
                    }

                }else 
                    AfxMessageBox(_T("FD_ISSET = FALSE"));

            }else{
                
                SOCKET_Close();
                SOCKET_Open();

                (*error) = _T("SOCKET TIMEOUT");
                break; //timeout

                zz.Format(_T("err_code: %d"),err_code);
                AfxMessageBox(zz);
            }

        }
        AfxMessageBox(_T("KRAJ"));

        CloseHandle(hFile);
        delete[] rcvBuff;
        rcvBuff = NULL;

        return;
    }


ovo je funkcija SOCKET_Open():
Code:

BOOL CConnection::SOCKET_Open()
{
    WSADATA wsaData;
    int sndSockBufsize = 65536, rcvSockBufsize = 131072;
    
    if(WSAStartup(MAKEWORD(2,2), &wsaData))
        return FALSE;

    s_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
    
    if (s_socket == INVALID_SOCKET || s_socket == SOCKET_ERROR)
        return FALSE;

    CString server_ip = data.ReadConfigValue(&csArrayConfig, _T("SERVER_IP"));
    int server_port = _ttoi(data.ReadConfigValue(&csArrayConfig, _T("SERVER_PORT")));
    
    SOCKADDR_IN SoketConf;
    SoketConf.sin_family = PF_INET;
    SoketConf.sin_port =  htons(server_port);
    SoketConf.sin_addr.s_addr =  data.ConvertIpAddress(server_ip);
 
    int is_connected = 0;
    do{
        is_connected = connect(s_socket, (struct sockaddr*)&SoketConf, sizeof(SoketConf));
    }
    while(select(0, 0, NULL, NULL, &timeoutSERVERA) == 0 || is_connected == 0 );  // timeoutSERVERA je 90 sec

    if(s_socket == INVALID_SOCKET){
        AfxMessageBox(_T("(OS) MOLIMO VAS POKUSAJTE PONOVO."),MB_OK|MB_ICONERROR);
        return FALSE;
    }

    setsockopt(s_socket, IPPROTO_TCP, SO_SNDBUF, (char *)&sndSockBufsize, (int)sizeof(sndSockBufsize)); 
    setsockopt(s_socket, IPPROTO_TCP, SO_RCVBUF, (char *)&rcvSockBufsize, (int)sizeof(rcvSockBufsize));
    
    return TRUE;

}
 
Odgovor na temu

Mihajlo Cvetanović
Beograd

Moderator
Član broj: 37636
Poruke: 1239



+94 Profil

icon Re: pitanja u vezi funkcije recv (WinSocket)20.10.2010. u 23:37 - pre 149 meseci
Ono što se možda dešava je da ti zapravo dobiješ završnu kombinaciju karaktera, ali je zagubiš, to jest ignorišeš, u svom kodu. Da li je ta kombinacija upisana u fajl?

Uočio sam još jedan potencijalni problem s kodom. Ti u kodu ispituješ da li je broj pročitanih bajtova x>6, pa ako jeste onda ispituješ da li se tu nalazi završna sekvenca. To sa TCP/IP komunikacijom ne ide baš tako. Šta ako dobiješ prvo 3, pa u sledećem cugu druga 4 bajta? Apsolutno ništa ti nije zagarantovano po pitanju implicitne podele streama na poruke. U pitanju je stream, bajtovi ti dolaze onim redom koji su poslati, ali to je jedina zagarantovana stvar. Drugim rečima, ako na kraju recv bafera detektuješ početak svoje završne sekvence, onda moraš da zapamtiš "gde si stao", i proveriš da li je nastavak sekvence primljen u sledećem recv.

X Files je objašnjavao razne situacije, pa i ovu sad, jedan predajnikov SEND može da proizvede više prijemnikovih READ-ova. Probaj da skapiraš ceo njegov tekst.
 
Odgovor na temu

Shejn
Srbija

Član broj: 11830
Poruke: 232
*.dynamic.sbb.rs.



Profil

icon Re: pitanja u vezi funkcije recv (WinSocket)21.10.2010. u 00:01 - pre 149 meseci
Zavrsna kombinacija ne moze da se pojavi u poruci i ide se sa pretpostavkom da ce stici vise od 6 karaktera, ukoliko ne stigne desice se timeout i to je to. Znam da je rupa, razmisljao sam vec da to izmenim .. ali za sada me muci ovaj drugi problem.

No, problem je sledeci:

primer 1:
poslato:
aaaaaaaaaa\r\n
bbbbbbbbb\r\n
ccccccccccc\r\n
....
end_of_send_data

ukupno 2000 bytes

funkcija RECEIVE_Data() ispisuje poruke:

"stiglo: 13 byte"
"upisano u fajl:13 byte"
< pauza 30 sekundi >
"SOCKET TIMEOUT"

pogledam u fajlu i ono stoji:
aaaaaaaaaa
+ \r\n

primer 2:
poslato:
aaaaaaaaaa\r\n
bbbbbbbbb\r\n
ccccccccccc\r\n
end_of_send_data\r\n

samo ovo navedeno

funkcija RECEIVE_Data() ispisuje poruke:

"stiglo: 13 byte"
"upisano u fajl:13 bytes"
"stiglo: 27 byte"
"upisano u fajl:27 bytes"
"DETEKTOVAN KRAJ."

pogledam u fajlu i ono stoji:
aaaaaaaaaa
bbbbbbbbb
ccccccccccc
end_of_send_data
+ \r\n


 
Odgovor na temu

Mihajlo Cvetanović
Beograd

Moderator
Član broj: 37636
Poruke: 1239



+94 Profil

icon Re: pitanja u vezi funkcije recv (WinSocket)21.10.2010. u 09:10 - pre 149 meseci
Možda je problem u RECEIVE_End(). Daj kod. Uzgred, koja je sad pa funkcija RECEIVE_Data(), jer ovo što sad imamo je valjda RECEIVE_File()?
 
Odgovor na temu

Shejn
Srbija

Član broj: 11830
Poruke: 232
*.dynamic.sbb.rs.



Profil

icon Re: pitanja u vezi funkcije recv (WinSocket)21.10.2010. u 15:15 - pre 149 meseci
Citat:
Mihajlo Cvetanović: Možda je problem u RECEIVE_End(). Daj kod. Uzgred, koja je sad pa funkcija RECEIVE_Data(), jer ovo što sad imamo je valjda RECEIVE_File()?

Jest, mislio sam na RECEIVE_File() funkciju .. moja greska.

Evo je funkcija RECEIVE_End():
Code:

BOOL CConnection::RECEIVE_End(int tipReceiva, char *niz, int length)
{
    //w3 = 0x0D;
    //w4 = 0x00;
    //w5 = 0x0A;
    //w6 = 0x00;
    //w7 = 0x31;
    //w8 = 0x00;

    CString temp, temp1;
    BOOL ret = FALSE;

    switch(tipReceiva)
    {    
        case 0:
            if(length <1)
                ret = FALSE;
            
            if( niz[length-1]==w5 && //0x0A
                niz[length]==w6      //0x00
              ) ret = TRUE;
        break;

        case 1: //kraj fajla je 1\r\n ali dvobajtno
            if(length <6)
                ret = FALSE;
                
            if(niz[length-6] == w7 &&   //0x31
                niz[length-5] == w8 &&  //0x00
                niz[length-4] == w3 &&  //0x0D
                niz[length-3] == w4 &&  //0x00
                niz[length-2] == w5 &&  //0x0A
                niz[length-1] == w6 &&  //0x00
                niz[length] == w6        //0x00
              ) ret = TRUE;
        break;

        case 2:
            if(length <4)
                ret = FALSE;

            if(niz[length-4] == w3 &&   //0x0D
                niz[length-3] == w4 &&  //0x00
                niz[length-2] == w5 &&  //0x0A
                niz[length-1] == w6 &&  //0x00
                niz[length] == w6        //0x00
              ) ret = TRUE;
        break;

        default:
            ret = FALSE;
        break;
    
    }

    return ret;
}
 
Odgovor na temu

Mihajlo Cvetanović
Beograd

Moderator
Član broj: 37636
Poruke: 1239



+94 Profil

icon Re: pitanja u vezi funkcije recv (WinSocket)21.10.2010. u 15:38 - pre 149 meseci
Može ladno da se desi ono što smo ti pričali. Tebi je marker za kraj slanja 0x0A,0x00, što je 2 bajta, ali pre poziva funkcije ti pitaš da li si primio 6 bajtova. Pošto nisi primio 6 nego 2 onda se i ne poziva RECEIVE_End().

EDIT: Greška, dva bajta su za tipReceiva==0.

[Ovu poruku je menjao Mihajlo Cvetanović dana 21.10.2010. u 16:49 GMT+1]
 
Odgovor na temu

Mihajlo Cvetanović
Beograd

Moderator
Član broj: 37636
Poruke: 1239



+94 Profil

icon Re: pitanja u vezi funkcije recv (WinSocket)21.10.2010. u 15:52 - pre 149 meseci
Malo mi je čudan ovaj poslednji 0x00 bajt, otkud sad on tu? Zar ne bi trebalo da bude samo 6 bajtova, Unicode "1\r\n"? Zašto imamo još jedan NUL?
 
Odgovor na temu

Shejn
Srbija

Član broj: 11830
Poruke: 232
*.dynamic.sbb.rs.



Profil

icon Re: pitanja u vezi funkcije recv (WinSocket)21.10.2010. u 18:16 - pre 149 meseci
Citat:
Mihajlo Cvetanović: Malo mi je čudan ovaj poslednji 0x00 bajt, otkud sad on tu? Zar ne bi trebalo da bude samo 6 bajtova, Unicode "1\r\n"? Zašto imamo još jedan NUL?

i meni je cudno, ali cini mi se da je to zato sto mi salje string, a on je null terminated(mozda gresim)

jos malo sam prosirio funkciju RECEIVE_File(), tako da sada radim i detekciju greske valjano ..

Code:

void CConnection::RECEIVE_File(CString naziv_fajla, BOOL sinhro, CString *error)
{
    int rcvLen=0, rcvBuffLen=256, endBuffLen=0;
    SYSTEMTIME localTime;
    DWORD dw1, dw2;

    char *endBuff = NULL;
    endBuff = new char[13];
    memset(endBuff, '\0', 13);

    char *rcvBuff = NULL;
    rcvBuff = new char[rcvBuffLen];
    memset(rcvBuff, '\0', rcvBuffLen);
    
    char *bomBuff = NULL;
    bomBuff = new char[2];
    memset(bomBuff, '\0', 2);

    HANDLE hFile = CreateFile(naziv_fajla, GENERIC_WRITE | GENERIC_READ,FILE_SHARE_READ, NULL, CREATE_ALWAYS, NULL, NULL);

    if (hFile == INVALID_HANDLE_VALUE)
    {
        (*error) = _T("(RD2) GRESKA PRI KREIRANJU FAJLA.\n\rMOLIMO VAS POKUSAJTE PONOVO.");
        CloseHandle(hFile);
        return;
    }

    //BOM
    dw2 = 2;
    bomBuff[0] = (char)w1;
    bomBuff[1] = (char)w2;
    WriteFile( hFile, bomBuff, dw2, &dw1, NULL);
    delete[] bomBuff;
    bomBuff = NULL;
    
    fd_set fdReadSet;
    FD_ZERO(&fdReadSet);
    FD_SET(s_socket, &fdReadSet);
    fdReadSet.fd_array[0] = s_socket;
    fdReadSet.fd_count = 1;
    TIMEVAL tO;

    tO.tv_sec = 15;
    tO.tv_usec = 0;

    CString zz;
    int err_code = -1;
    BOOL cesljaj = TRUE;
    
    while(cesljaj)
    {
        FD_ZERO(&fdReadSet);
        FD_SET(s_socket, &fdReadSet);

        if ((err_code = select(0, &fdReadSet, NULL, NULL, &tO)) == SOCKET_ERROR)
        {
            SOCKET_Close();
            SOCKET_Open();

            (*error) = _T("SOCKET ERROR");
            cesljaj = FALSE; //timeout

        }

        if(err_code > 0)
        {

            if (FD_ISSET(s_socket, &fdReadSet))
            {

                memset(rcvBuff, '\0', rcvBuffLen);
                rcvLen = recv(s_socket, rcvBuff, rcvBuffLen, 0);

                if(rcvLen == SOCKET_ERROR)
                {
                    SOCKET_Close();
                    SOCKET_Open();

                    FD_ZERO(&fdReadSet);
                    FD_SET(s_socket, &fdReadSet);
                    fdReadSet.fd_array[0] = s_socket;
                    fdReadSet.fd_count = 1;
                    
                    (*error) = _T("SOCKET ERROR");
                    cesljaj = FALSE;

                }
                else
                {
                    dw2 = rcvLen;
                    WriteFile( hFile, rcvBuff, dw2, &dw1, NULL);
                    
                                        //kraj je 1\r\n  tj. 0x31, 0x00, 0x0D,  0x00, 0x0A, 0x00, 0x00
                    if(rcvLen > 6)
                    { 
                        //isprazni endBuff
                        memset(endBuff, '\0', 13);
                        endBuffLen = 0;
                        
                        
                        //uzme samo poslednjih 7 iz rcvBuff i upise u endBuff .. endBuffLen = 7
                        data.concatCharP(endBuff, rcvBuff, rcvLen, 7, &endBuffLen);
                    
                    }else{
                        //ovde x moze biti maks. 6
                        data.concatCharP(endBuff, rcvBuff, rcvLen, rcvLen, &endBuffLen);
                    }


                    /*ako je endBuffLen manje od potrebne velicine kraja ne radi se provera kraja*/
                    if(endBuffLen > 6)
                    {
                        if( RECEIVE_End(1, endBuff, endBuffLen))
                        {
                            SOCKET_Close();
                            SOCKET_Open();

                            AfxMessageBox(_T("DETEKTOVAN KRAJ."));
                            
                            cesljaj = FALSE;
                        }

                    }

                }

            }else{
                AfxMessageBox(_T("FD_ISSET = FALSE"));
                cesljaj = FALSE; //timeout
            }

        }else{

            (*error) = _T("SOCKET TIMEOUT");
            cesljaj = FALSE; //timeout
        }

    }
    AfxMessageBox(_T("KRAJ"));

    CloseHandle(hFile);
    delete[] rcvBuff;
    delete[] endBuff;
    rcvBuff = NULL;
    endBuff = NULL;

    return;
}


funkcija concatCharP()
Code:

void CData::concatCharP(char * endBuff, char * rcvBuff, int rcvBuffLen, int offset, int * endBuffLenn)
{
    int t;
    int i = *endBuffLenn;
    for (t = (rcvBuffLen-offset); t < rcvBuffLen; t++)
    {
        endBuff[i] = rcvBuff[t];
        i++;
    }

    *endBuffLenn += i;
}
 
Odgovor na temu

Mihajlo Cvetanović
Beograd

Moderator
Član broj: 37636
Poruke: 1239



+94 Profil

icon Re: pitanja u vezi funkcije recv (WinSocket)21.10.2010. u 19:09 - pre 149 meseci
Skini ti ipak tu proveru niz[length] == w6 , meni to smrdi na višak. Uostalom, niz je ispravan samo u opsegu od 0 do length-1.
 
Odgovor na temu

Shejn
Srbija

Član broj: 11830
Poruke: 232
*.dynamic.sbb.rs.



Profil

icon Re: pitanja u vezi funkcije recv (WinSocket)22.10.2010. u 01:17 - pre 149 meseci
E sad neces poverovati sta je uzrokovalo kvar.
Komunikacija sa serverom se radi putem GPRS-a, preko SIM kartice (u pitanju je pda uredjaj).
Kartica koja se koristi je kartica Srpskog najveceg provajdera .. i gle cuda tu je zapelo. Iz nekog misterioznog razloga su sasekli poruke koje su stizale od servera ka klijentu.
Kada sam promenuo karticu sa karticom drugog (po zastupljenosti) 'Srpskog' provajdera sve je proradilo.

Ako nista drugo bar smo se lepo ispricali, i prokometarisali kod :).



Pozdrav, hvala na pomoci i svako dobro.
 
Odgovor na temu

Mihajlo Cvetanović
Beograd

Moderator
Član broj: 37636
Poruke: 1239



+94 Profil

icon Re: pitanja u vezi funkcije recv (WinSocket)22.10.2010. u 09:30 - pre 149 meseci
Lepo je to, ali nisam siguran da prvi provajder baš iseče poruku. Pre će biti da je segmentira, to jest pošalje u više TCP paketa (to je ona priča od X Files-a). Udovolji mi molim te, i pogledaj preko Wiresharka na serverskoj strani šta server tačno šalje za onaj problematični slučaj. Koji su poslednjih 10 bajtova, uključujući i NUL karaktere. Dajem glavu da poslednja dva bajta nisu 00,00 nego 0A,00. U Windowsu Unicode je Little-Endian, to jest za svaki par bajtova u nultoj Unicode stranici prvo ide korisni bajt, pa onda nula. Ova poslednja nula nema svog parnjaka, i pritom se nalazi van granica niza, tako da ta nula ponekad postoji, a ponekad ne. To je greška, i ta poslednja nula ne treba da se proverava.

Kad skineš tu poslednju nulu onda probaj ponovo sa prvim provajderom.
 
Odgovor na temu

Shejn
Srbija

Član broj: 11830
Poruke: 232
*.dynamic.sbb.rs.



Profil

icon Re: pitanja u vezi funkcije recv (WinSocket)22.10.2010. u 14:01 - pre 149 meseci
Pa cekaj, zar to nije null karakter koji ja upisem prilikom kreiranja buffera?
char *endBuff = NULL;
endBuff = new char[13];
memset(endBuff, '\0', 13); <- endBuff je duzine 13+null karakter

No, mislim da nije tu problem,
evo sta sam probao

AfxmessageBox(_T("START"))
select
AfxmessageBox(_T("PRE RECV"))
recv
AfxmessageBox(_T("POSLE RECV"))
write
AfxmessageBox(_T("POSLE WRITE"))
RECEIVE_End
AfxmessageBox(_T("POSLE RECEIVE_End"))

i sta se desava je sledece

1. krug
"START"
"PRE RECV"
"POSLE RECV"
"POSLE WRITE"
"POSLE RECEIVE_End"

2. krug
"START"
"PRE RECV"
--------------> TIMOUT


Sto ce reci da nije problem sa funkcijom RECEIVE_End()

Sa druge strane, kazem ti, kada sam promenio SIM karticu sve radi ok .. detektuje se kraj sa RECEIVE_End() i izadje iz petlje.


 
Odgovor na temu

Mihajlo Cvetanović
Beograd

Moderator
Član broj: 37636
Poruke: 1239



+94 Profil

icon Re: pitanja u vezi funkcije recv (WinSocket)22.10.2010. u 14:28 - pre 149 meseci
Moja je teorija da se zaglavio u recv zato što u prethodnom krugu nije detektovao kraj.

I naravno, ako si rezervisao 13 karaktera za bafer onda ne možeš bez posledica da upišeš 14 u njega, koliko god da si dobar programer :-)
 
Odgovor na temu

[es] :: C/C++ programiranje :: pitanja u vezi funkcije recv (WinSocket)

Strane: 1 2

[ Pregleda: 3091 | Odgovora: 21 ] > FB > Twit

Postavi temu Odgovori

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