booyaka Temat założony przez niniejszego użytkownika |
Komunikacja klient-serwer przez socket() » 2013-12-16 17:22:17 Witam, Mam wykonać takie zadanie: Klient ma przesłać do serwera dane a, b, c. Serwer ma je odebrać, obliczyć pierwiastki funkcji kwadratowej ax^2 + bx + c i odesłać je do klienta. Mój kod nie działa do końca poprawnie, odbiera tylko dane a i b. kod serwer: #include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <stdlib.h> #include <sys/un.h> #include <unistd.h>
void blad() { perror( "Blad Serwera" ); exit( 1 ); }
int main() { int gniazdo_serwera; int gniazdo_dla_klienta; int serwer_dlugosc; int klient_dlugosc; int test1, test2, test3, test4, test5, test6, test7; int A, B, C; int suma; struct sockaddr_un adres_serwera; struct sockaddr_un adres_klienta; unlink( "gniazdo_serwera" ); test1 = gniazdo_serwera = socket( AF_UNIX, SOCK_STREAM, 0 ); if( test1 ==- 1 ) blad(); adres_serwera.sun_family = AF_UNIX; strcpy( adres_serwera.sun_path, "gniazdo_serwera" ); serwer_dlugosc = sizeof( adres_serwera ); test2 = bind( gniazdo_serwera,( struct sockaddr * ) & adres_serwera, serwer_dlugosc ); if( test2 ==- 1 ) blad(); test3 = listen( gniazdo_serwera, 5 ); if( test3 ==- 1 ) blad(); printf( "Serwer nasluchuje ... \n" ); while( 1 ) { gniazdo_dla_klienta = accept( gniazdo_serwera,( struct sockaddr * ) & adres_klienta, & klient_dlugosc ); test4 = read( gniazdo_dla_klienta, & A, 1 ); if( test4 > 0 ) printf( "Odebralem od klienta liczbe %d.\n", A ); else blad(); test5 = read( gniazdo_dla_klienta, & B, 1 ); if( test5 > 0 ) printf( "Odebralem od klienta liczbe %d.\n", B ); else blad(); test6 = read( gniazdo_dla_klienta, & C, 1 ); if( test6 > 0 ) printf( "Odebralem od klienta liczbe %d.\n", C ); else blad(); suma = A + B + C; test7 = write( gniazdo_dla_klienta, & suma, 1 ); if( test7 > 0 ) printf( "Wysylam dane do klienta suma %d.\n", suma ); else blad(); close( gniazdo_dla_klienta ); } close( gniazdo_serwera ); exit( 0 ); }
Kod klient: #include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <stdlib.h> #include <sys/un.h> #include <unistd.h>
void blad() { perror( "Blad Serwera" ); exit( 1 ); }
int main() { int gniazdo_klienta; int serwer_dlugosc; int suma; int A, B, C; int test1, test2, test3, test4, test5, test6, test7; struct sockaddr_un adres_serwera; test1 = gniazdo_klienta = socket( AF_UNIX, SOCK_STREAM, 0 ); if( test1 ==- 1 ) blad(); adres_serwera.sun_family = AF_UNIX; strcpy( adres_serwera.sun_path, "gniazdo_serwera" ); serwer_dlugosc = sizeof( adres_serwera ); test1 = connect( gniazdo_klienta,( struct sockaddr * ) & adres_serwera, serwer_dlugosc ); if( test1 ==- 1 ) blad(); printf( "A: \n" ); scanf( "%d", & A ); test4 = write( gniazdo_klienta, & A, 1 ); if( test4 > 0 ) printf( "Wyslalem do serwera liczbe %d.\n", A ); else blad(); printf( "B: \n" ); scanf( "%d", & B ); test5 = write( gniazdo_klienta, & B, 1 ); if( test5 > 0 ) printf( "Wyslalem do serwera liczbe %d.\n", B ); else blad(); printf( "C: \n" ); scanf( "%d", & C ); test6 = write( gniazdo_klienta, & C, 1 ); if( test6 > 0 ) printf( "Wyslalem do serwera liczbe %d.\n", C ); else blad(); test7 = read( gniazdo_klienta, & suma, 1 ); if( test7 > 0 ) printf( "Otrzymalem od serwera suma %d.\n", suma ); else blad(); close( gniazdo_klienta ); exit( 0 ); }
Z góry dziękuję za pomoc, |
|
DejaVu |
» 2013-12-16 17:33:35 write( gniazdo_klienta, & A, 1 );
|
O ile się nie mylę to funkcja write wysyła tyle bajtów ile podasz, czyli w Twoim przypadku wysyłasz 1 bajt (co jest złe). Wartości liczbowe należy również konwertować do postaci Network Byte Order w chwili wysyłania i odczytywać do Little Endiana lub Big Endiana przy ich odczytywaniu z sieci (są do tego funkcje, ale nie pamiętam teraz ich nazw). Druga opcja to wysyłać dane w postaci tekstu i konwertować je sobie po stronie klienta do zmiennych liczbowych. Odczyt ma ten sam błąd. |
|
Elaine |
» 2013-12-16 17:48:27 Wartości liczbowe należy również konwertować do postaci Network Byte Order w chwili wysyłania i odczytywać do Little Endiana lub Big Endiana przy ich odczytywaniu z sieci |
Nie trzeba, ważne jest tylko to, by obie strony połączenia wysyłały i odbierały dane w tym samym formacie. Czy tym formatem są cztery bajty LE, osiem bajtów BE czy tekst w EBCDIC to już decyzja programu, socketom jest всё равно. |
|
booyaka Temat założony przez niniejszego użytkownika |
» 2013-12-16 18:25:57 Poprawiłem trochę kod, pobiera już poprawnie wartości A, B, C. Tylko, że później je oblicza i wysyła do klienta, a klient odbiera nieprawidłowe dane. Nie potrafię się doszukać gdzie tkwi problem. Przykładowo dla danych: A = 1, B = 5, C = 4, x1 = -1, x2 = -4. Natomiast klient wyrzuca dane x1 = 255, x2 = 252. Wkleje jeszcze raz oba kody. Kod serwera: #include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <stdlib.h> #include <sys/un.h> #include <unistd.h> #include <math.h>
void blad() { perror( "Blad Serwera" ); exit( 1 ); }
int main() { int gniazdo_serwera; int gniazdo_dla_klienta; int serwer_dlugosc; int klient_dlugosc; int test1, test2, test3, test4, test5, test6, test7, test8; int A, B, C; int delta, pdelta, x1, x2; struct sockaddr_un adres_serwera; struct sockaddr_un adres_klienta; unlink( "gniazdo_serwera" ); test1 = gniazdo_serwera = socket( AF_UNIX, SOCK_STREAM, 0 ); if( test1 ==- 1 ) blad(); adres_serwera.sun_family = AF_UNIX; strcpy( adres_serwera.sun_path, "gniazdo_serwera" ); serwer_dlugosc = sizeof( adres_serwera ); test2 = bind( gniazdo_serwera,( struct sockaddr * ) & adres_serwera, serwer_dlugosc ); if( test2 ==- 1 ) blad(); test3 = listen( gniazdo_serwera, 5 ); if( test3 ==- 1 ) blad(); printf( "Serwer nasluchuje ... \n" ); A = 1; B = 2; C = 3; while( 1 ) { gniazdo_dla_klienta = accept( gniazdo_serwera,( struct sockaddr * ) & adres_klienta, & klient_dlugosc ); test4 = read( gniazdo_dla_klienta, & A, 1 ); if( test4 > 0 ) printf( "Odebralem od klienta liczbe %d.\n", A ); else blad(); test5 = read( gniazdo_dla_klienta, & B, 1 ); if( test5 > 0 ) printf( "Odebralem od klienta liczbe %d.\n", B ); else blad(); test6 = read( gniazdo_dla_klienta, & C, 1 ); if( test6 > 0 ) printf( "Odebralem od klienta liczbe %d.\n", C ); else blad(); delta =( B * B - 4 * A * C ); pdelta = sqrt( delta ); x1 =( - B + pdelta ) /( 2 * A ); x2 =( - B - pdelta ) /( 2 * A ); test7 = write( gniazdo_dla_klienta, & x1, 1 ); if( test7 > 0 ) printf( "Wysylam dane do klienta x1 %d.\n", x1 ); else blad(); test8 = write( gniazdo_dla_klienta, & x2, 1 ); if( test8 > 0 ) printf( "Wysylam dane do klienta x2 %d.\n", x2 ); else blad(); close( gniazdo_dla_klienta ); } close( gniazdo_serwera ); exit( 0 ); }
Kod klienta #include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <stdlib.h> #include <sys/un.h> #include <unistd.h>
void blad() { perror( "Blad Serwera" ); exit( 1 ); }
int main() { int gniazdo_klienta; int serwer_dlugosc; int x1, x2; int A, B, C; int test1, test2, test3, test4, test5, test6, test7, test8; struct sockaddr_un adres_serwera; test1 = gniazdo_klienta = socket( AF_UNIX, SOCK_STREAM, 0 ); if( test1 ==- 1 ) blad(); adres_serwera.sun_family = AF_UNIX; strcpy( adres_serwera.sun_path, "gniazdo_serwera" ); serwer_dlugosc = sizeof( adres_serwera ); test1 = connect( gniazdo_klienta,( struct sockaddr * ) & adres_serwera, serwer_dlugosc ); if( test1 ==- 1 ) blad(); printf( "A: \n" ); scanf( "%d", & A ); test4 = write( gniazdo_klienta, & A, 1 ); if( test4 > 0 ) printf( "Wyslalem do serwera liczbe %d.\n", A ); else blad(); printf( "B: \n" ); scanf( "%d", & B ); test5 = write( gniazdo_klienta, & B, 1 ); if( test5 > 0 ) printf( "Wyslalem do serwera liczbe %d.\n", B ); else blad(); printf( "C: \n" ); scanf( "%d", & C ); test6 = write( gniazdo_klienta, & C, 1 ); if( test6 > 0 ) printf( "Wyslalem do serwera liczbe %d.\n", C ); else blad(); x1 = 1; x2 = 2; test7 = read( gniazdo_klienta, & x1, 1 ); if( test7 > 0 ) printf( "Otrzymalem od serwera x1 %d.\n", x1 ); else blad(); test8 = read( gniazdo_klienta, & x2, 1 ); if( test8 > 0 ) printf( "Otrzymalem od serwera x2 %d.\n", x2 ); else blad(); close( gniazdo_klienta ); exit( 0 ); }
|
|
DejaVu |
» 2013-12-16 18:37:54 Nie poprawiłeś niczego z tego o czym pisałem. |
|
booyaka Temat założony przez niniejszego użytkownika |
» 2013-12-16 18:58:13 Nie poprawiłem, bo zdaje się działać bez tego, a dodatkowo zasugerowałem się tym co napisał Alueril.
Ogólnie rzecz biorąc to program "prawie" działa. W miejscu x1,x2 mogę przesłać dowolne wartości, delta, pdelta, sumaABC i wszystko działa w porządku. A przy przesyłaniu x1,x2 wysyła głupoty. Nie rozumiem kompletnie o co chodzi. |
|
Elaine |
» 2013-12-16 19:14:19 A = 1, B = 5, C = 4, x1 = -1, x2 = -4. Natomiast klient wyrzuca dane x1 = 255, x2 = 252. |
Wszystko się "zgadza". Wysyłasz i odbierasz jeden bajt, a w przypadku liczb w U2 LE pierwszym bajtem -1 i -4 jest 255 i 252. Wysyłaj i odbieraj całą liczbę, to dostaniesz -1 i -4. Mała rada: zamiast int warto użyć jakiegoś typu, którego rozmiar nie jest zależny od platformy, jak std::int32_t, żeby uniknąć zabawy przy portowaniu kodu. |
|
« 1 » |