[ milan82 @ 10.09.2005. 08:19 ] @
Pisem klijentsku aplikaciju u C-u koja treba slati upite serveru koji ce na njih odgovarati. Napravio sam neki privremeni spremnik tipa char buffer [100] preko kojega saljem upite. Medutim, server ne odgovara kako bi trebao jer ponekad samo napravi echo tj. vrati ono sto sam poslao. Pokusao sam sa dva buffera, jedan za slanje a drugi za primanje i opet imam slicnu stvar. U cemo moze biti problem, sa kojim pristupom bi jos mogao pokusati? Napominjem da serverski kod ne smijem mijenjati.
[ X Files @ 10.09.2005. 08:32 ] @
Pretpostavljam da ti niko nece moci pomoci bez parceta tvog konkretnog koda...

[ itf @ 10.09.2005. 08:33 ] @
Evo, baš sam nešto radio u vezi toga prethodnih dana... SERVER-KLIJENT komunikacija:

SERVER.CPP
------------
Code:
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>

struct student{
    char ime[20];
    char prez[20];
    char matbr[15];
    char JMBG[15];
    short kz1;
    short kz2;
    short lab;
    float ukupno;
    short ocjena;
};

//treba linkati sa Ws2_32.lib
void win32stuff(){
    WSADATA wsaData;

    if(WSAStartup(MAKEWORD( 2, 2 ), &wsaData)){
        fprintf(stderr, "Ne mogu inicijalizirati mrezu\n");
        exit(1);
    }

    if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 ) {
        /* Tell the user that we could not find a usable */
        /* WinSock DLL.                                  */

        fprintf(stderr, "Ne mogu inicijalizirati prave parametre\n");
        WSACleanup( );
        exit(1);
    }
}


int main(){
    int sock, lenght, bodovi = 0, ocjena = 0;
    struct sockaddr_in name, client;
    char buf[1000];

    win32stuff();

    sock=socket(AF_INET, SOCK_DGRAM, 0);
    
    if( sock<0 ){
        perror("Nece stvoriti socket\n");
        exit(1);
    }
    
    name.sin_family = AF_INET;
    name.sin_addr.s_addr = INADDR_ANY;
    name.sin_port=htons(10000);
    
    if( bind(sock, (struct sockaddr*) &name, sizeof(name) )<0 ){
        perror("Nece bindati\n");
        exit(1);
    }
    
    lenght=sizeof(name);
    
    if(getsockname(sock, (struct sockaddr*) &name, &lenght)<0){
        perror("Getsocket error\n");
        exit(1);
    }
    
    printf("Socket je na portu: %d, ja slusam:\n", ntohs(name.sin_port));
    
    while(1){
        if( recvfrom(sock, buf, 1024,0, (struct sockaddr*) &client, &lenght)<0 )
            perror("Nece ili nema sto za citati\n");
        else{
            printf("=>%s\n", buf);
            bodovi = 0;
            ocjena = 0;
                                      // obradi dobivene podatke
            // Rezultati(buf, &bodovi, &ocjena);
            sprintf(buf, "%s %d %d\n", buf, bodovi, ocjena);
            if( sendto(sock, buf, strlen(buf)+1, 0, (struct sockaddr*) &client, sizeof(name))<0 ){
                perror("Nece slati\n");
                exit(1);
            }
        }
        
        if(buf[0]=='e' && buf[1]=='n' && buf[2]=='d')
            break;
    }
    closesocket(sock);
    return 0;
}


KLIJENT.CPP
-----------
Code:
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>

//treba linkati sa Ws2_32.lib
void win32stuff(){
    WSADATA wsaData;

    if(WSAStartup(MAKEWORD( 2, 2 ), &wsaData)){
        fprintf(stderr, "Ne mogu inicijalizirati mrezu\n");
        exit(1);
    }

    if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 ) {
        /* Tell the user that we could not find a usable */
        /* WinSock DLL.                                  */

        fprintf(stderr, "Ne mogu inicijalizirati prave parametre\n");
        WSACleanup( );
        exit(1);
    }
}

void main(int argc, char *argv[]){
    int sock;
    struct sockaddr_in name;
    struct hostent *hp;
    char buf[1000];
    
    win32stuff();

    sock=socket(AF_INET, SOCK_DGRAM, 0);
    
    if(argc<4){
        perror("Upotreba: program racunalo port poruka\n");
        getchar();
        exit(1);
    }
    if( sock<0 ){
        perror("Nece stvoriti socket\n");
        exit(1);
    }
    
    hp=gethostbyname(argv[1]);
    
    if(hp==0){
        perror("%s - nepoznat host!\n");
        exit(1);
    }
    
    memcpy ( (char*) &name.sin_addr, (char*)hp->h_addr, hp->h_length);
    
    name.sin_family = AF_INET;
    name.sin_port=htons(atoi(argv[2]));
    
    if( sendto(sock, argv[3], strlen(argv[3])+1, 0, (struct sockaddr*) &name, sizeof(name))<0 ){
        perror("Nece slati\n");
        exit(1);
    }
    if( recv(sock, buf, 1024,0)<0 )
        perror("Nece ili nema sto za citati\n"); 
    else 
        printf("=>%s\n", buf);  

    closesocket(sock);
}


Ovo sam radio za jedan predmet na faksu pa ćeš dosta toga moći i eliminirati :)

[Ovu poruku je menjao itf dana 10.09.2005. u 09:37 GMT+1]
[ milan82 @ 10.09.2005. 08:47 ] @
Hvala itf na kodu, vidim da si to ostvario preko stream klijenta i servera, mozda bi to pomoglo.
[ X Files @ 10.09.2005. 08:48 ] @
Code:

// ...
char buf[1000];
// ...
if( recv(sock, buf, 1024,0)<0 )
// ...


1000 < 1024 ?

Mozda neki #define BUFF 1000
[ itf @ 10.09.2005. 08:50 ] @
Ma sad sam tu nešto brisao jer je bila hrpa nepotrebnih stvari pa je i to nestalo. Uostalom, ako se već čovjek bavi tim stvarima to mu je najmanji problem ;)

Evo tu je opisano mnogo detaljnije

http://www.zemris.fer.hr/~leonardo/mreze/umr/lab6/vjezba6.htm
http://www.zemris.fer.hr/~leonardo/mreze/umr/lab7/vjezba7.htm


[Ovu poruku je menjao itf dana 10.09.2005. u 09:53 GMT+1]
[ X Files @ 10.09.2005. 08:55 ] @
Ma naravno, salim se ;)

itf:
Imas TClientSocket i TServerSocket kod Borland C++ Builder-a...



[ itf @ 10.09.2005. 08:58 ] @
TO NE RADI! Baš me naživciralo jer stalno puca program koji sadži te komponente. Izgleda da su outdated. Ajd javi ako tebi to radi. Imaš gotov primjer u examples direktoriju
[ X Files @ 10.09.2005. 09:02 ] @
Radi, radi ;)

Cucemo se, imam svoj kod... Neki serveri koje sam uradio rade evo vec 4-ta godina
bez problema...


[ itf @ 10.09.2005. 09:05 ] @
Meni pukne kada pošaljem drugu poruku. Još prva je OK, ali već na drugoj puca. A ništa.... Valjda je nešto do OS-a.. Baš si pokušao na 127.0.0.1? Onaj CHAT primjer?

[Ovu poruku je menjao itf dana 10.09.2005. u 10:05 GMT+1]
[ X Files @ 10.09.2005. 09:11 ] @
Problem kod skoro svih primera koji se bave socket-ima je sto polaze od
pretpostavke da ce CEO BUFFER biti poslat ODJEDNOM sto je nedospustivo
sa stanovista TCP/IP protokola.

Najgore je sto takvi primeri zaista (u startu) i prorade jer se radi najcesce
o jednoj te istoj masini gde je i klijent i server, i sto se radi o zaista malim
kolicinama podataka poslatim u 'laboratorisjkim' uslovima.

U praksi to puca 100%.

Dakle, gluposti tipa SendText() / ReceiveText() su samo za izlozbu a ne i za
ozbiljan rad.

Dakle, klijent treba da pokusa slanje:

1) celog buffera ili
2) nekog obranicenog buffera da '8192' bajta

... onda se ocitava povratna vrednost KOLIKO je zaista bajtova poslato, pa se
odatle i nastavlja, itd...

kod servera je slicno, cita se koliko je primljeno, i to se belezi u nekakab buffer.
Prethodno je JAKO PAMETNO da prva 4 bajta u protokolu budu UKUPNA DUZINA
buffera, itd...


Otom potom, cucemo se...

[ itf @ 10.09.2005. 09:18 ] @
Ma uopće se ne kanim sad time zafrkavati. Ako bude trebalo napravit ću ATL komponentu u .NET-u (ovo gore što sam napisao a radi) i registriram je u Borlandu.
[ X Files @ 10.09.2005. 09:23 ] @
Moze i tako...

Inace, uza specijalnost su mi serveri:

Servisna aplikacija + client/server komponente...

... pa ako ti zatreba tu sam.
[ insomniac_st @ 12.09.2005. 10:48 ] @
Nisam uspio rijesit problem:(
Imam buffer tipa: char buffer [MAXDATASIZE]; (size je 100, nije to vazno,mislim)
saljem sa: gets(buffer); i send(create_socket,buffer, MAXDATASIZE ,0);
primam: recv( create_socket, buffer ,MAXDATASIZE,0); i puts(buffer)
Komunikacija je ostvarena, medutim u bufferu ponekad "nesto ostaje" pa mi server vrati dio poslanog zahtjeva sto ne bi smio.
socket je tipa: (create_socket = socket(AF_INET,SOCK_STREAM,0)
Mozda moze biti problem sto server prima sintaksu: \<nesto ovdje>/ jer je \ escape sekvenca...
(malo sam izmjesao logine, post je od milan82 ...)

[Ovu poruku je menjao insomniac_st dana 12.09.2005. u 11:50 GMT+1]
[ X Files @ 12.09.2005. 13:31 ] @
Cekaj, hoces da kazes da server 'prima' protokol u formatu:

\ . . . n e k i b u f f e r . . . /

... pri cemu je pocetak obrnuta kosa crta i kraj obicna kosa crta?

Ako je tako, pokazi kako si u programu smestio taj buffer... Moze se desiti da si sa
Escape-om unistio pocetak protokola...


[ insomniac_st @ 12.09.2005. 14:14 ] @
Da, naredbe su oblika \<naredba>/, i sad, ja sam pokusao sa gets (post ranije) i sa:

printf ("Unesi naredbu:");
scanf("%s", &naredba);
sprintf(buffer,"%s", naredba);
write (create_socket,buffer,100);
read (create_socket,buffer,100);
sscanf( buffer,"%s",&odgovor);
printf("\n%s\n",odgovor);

a imam char buffer[1024], char naredba[100] i char odgovor[100]

... i opet ne dobijem sto mi treba, imas kakvu ideju?


[ itf @ 12.09.2005. 17:14 ] @
Jesi pogledao one gore linkove?
[ yooyo @ 12.09.2005. 17:22 ] @
Zar ne bi trebalo:

write (create_socket,naredba,strlen(naredba));


A za read se moras malo pomuciti.. tj. ne garantuje se da ces ceo pake dobiti odjednom (mada kratki paketici stizu u komadu), nego se moze desiti iz delova. Zato moras citati paketic po paketic i da sve to skupljas u neki "incoming" buffer. Posle svakog dodavanja u incoming buffer proveri da se u incoming bufferu nalaze cela komanda i tek je tada mozes izvrsiti.

Prilikom mrezne komunikacije obicno se na pocetku svakog paketa ubaci njegova duzina tako da onaj koji prima paket zna koliko bajtova moze da ocekuje.

yooyo
[ insomniac_st @ 13.09.2005. 11:36 ] @
@yooyo: Hvala, dosta mi je tvoj post pomogao, al opet ne znam kako to rjesiti. Napravio sam:

read (create_socket,buffer,sizeof(buffer));
sscanf( buffer,"%s",&odgovor);
int pp = strlen(odgovor);
printf ("\nodgovor size: %d",pp);

printf("\nodgovor: %s",odgovor);
(pokusao sam i sa strlen-om) Odgovor spremam u buffer, na izlazu dobijem da je duljina odgovora 4 a meni se prikaze ili nista ili djelic odgovora, znaci opet dobijem odgovor u dijelovima. Naravio sam:
do
{
read (create_socket,buffer,strlen(buffer));
}
while (strlen(buffer) > 2);

i opet nista.?

@itf: pogledao sam, nije pomoglo:(
[ bzero @ 13.09.2005. 12:04 ] @
Citat:

read (create_socket,buffer,sizeof(buffer));
sscanf( buffer,"%s",&odgovor);
int pp = strlen(odgovor);
printf ("\nodgovor size: %d",pp);


Ovo ne treba da radis. read() vraca broj bajtova koji je stvarno procitao i stavio u buffer. Procitaj man read i ono sto je yooyo napisao.
[ insomniac_st @ 14.09.2005. 08:51 ] @
Shvatio sam neke stvari pa sam napravio ovo:

Code:
 
            int br=read (create_socket,buffer,strlen(buffer));
         printf("\nprimljeno: %d\n",br);
    
        if (br > 0)
        {
          buffer[br] = '\0';
          printf (buffer);
        }
      else if (br == 0)
        break;
      else if (br < 0)
          printf("\nGreska!");
       


I imam ispis da dobijem 4 bajta i ne prikaze mi se sve kako treba. Moze neki primjer kako bi rjesio punjenje buffera i ispravan ispis?
[ yooyo @ 14.09.2005. 09:52 ] @
Ocito ne kapiras... pokusaj na ovaj nacin.

Code:

slanje:
send(create_socket,naredba,strlen(naredba)+1); // posalji string i \0 na kraju

prijem:
int pos=0, len;
do
{
 len = recv(create_socket, buffer + pos, 1000,0); // len vraca ukupan broj procitanih. 1000 je max duzina buffera
 pos = pos + len;
} while (buffer[pos-1] != 0);


yooyo
[ insomniac_st @ 14.09.2005. 10:56 ] @
Pokusao sam, ne radi, problem je u do-while petlji. Provjerio sam da uredno posalje, onda udje u petlju i tu program stane ...
[ yooyo @ 14.09.2005. 11:34 ] @
Probaj da debagujes program red po red, vidi sta se desva u do-while petlji. Mozda je konekcija zatvorena pa recv vraca SOCKET_ERROR u len.

Jos nesto.. ako je u pitanju server program, onda imas treba da ims jedan socket u listen modu i sa accept prihvatas nove konekcije. Accept vraca NOVI socket za svakog klijenta koji se poveze i sva dalja komunikacija sa tim klijentom ide preko tog novog socket-a.

yooyo