|
[ 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
Copyright (C) 2001-2025 by www.elitesecurity.org. All rights reserved.
|