Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Komunikacja klient-serwer przez socket()

Ostatnio zmodyfikowano 2013-12-16 19:14
Autor Wiadomość
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:
C/C++
#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;
   
   
    // Usuniecie starego gniazda
    unlink( "gniazdo_serwera" );
   
    //Utworzenie gniazda serwera
    test1 = gniazdo_serwera = socket( AF_UNIX, SOCK_STREAM, 0 );
    if( test1 ==- 1 ) blad();
   
    //Zwiazanie gniazda serwera z adresem
    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();
   
    //Utworzenie kolejki dla oczekujacych polaczen
    test3 = listen( gniazdo_serwera, 5 );
    if( test3 ==- 1 ) blad();
   
    printf( "Serwer nasluchuje ... \n" );
   
    // Komunikacja gniazda serwera z gniazdem klienta
    while( 1 )
    {
        //Przyjecie polaczenia przez gniazdo serwera
        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:
C/C++
#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;
   
    //Utworzenie gniazda klienta
    test1 = gniazdo_klienta = socket( AF_UNIX, SOCK_STREAM, 0 );
    if( test1 ==- 1 ) blad();
   
    //Ustalenie adresu serwera
    adres_serwera.sun_family = AF_UNIX;
    strcpy( adres_serwera.sun_path, "gniazdo_serwera" );
    serwer_dlugosc = sizeof( adres_serwera );
    //Polaczenie gniazda klienta z gniazdem serwera
    test1 = connect( gniazdo_klienta,( struct sockaddr * ) & adres_serwera, serwer_dlugosc );
    if( test1 ==- 1 ) blad();
   
    //Komunikacja gniazda serwera z gniazdem klienta
    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,
P-99368
DejaVu
» 2013-12-16 17:33:35
C/C++
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.
P-99369
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 всё равно.
P-99373
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:

C/C++
#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;
   
   
    // Usuniecie starego gniazda
    unlink( "gniazdo_serwera" );
   
    //Utworzenie gniazda serwera
    test1 = gniazdo_serwera = socket( AF_UNIX, SOCK_STREAM, 0 );
    if( test1 ==- 1 ) blad();
   
    //Zwiazanie gniazda serwera z adresem
    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();
   
    //Utworzenie kolejki dla oczekujacych polaczen
    test3 = listen( gniazdo_serwera, 5 );
    if( test3 ==- 1 ) blad();
   
    printf( "Serwer nasluchuje ... \n" );
   
    A = 1;
    B = 2;
    C = 3;
   
    // Komunikacja gniazda serwera z gniazdem klienta
    while( 1 )
    {
        //Przyjecie polaczenia przez gniazdo serwera
        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
C/C++
#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;
   
    //Utworzenie gniazda klienta
    test1 = gniazdo_klienta = socket( AF_UNIX, SOCK_STREAM, 0 );
    if( test1 ==- 1 ) blad();
   
    //Ustalenie adresu serwera
    adres_serwera.sun_family = AF_UNIX;
    strcpy( adres_serwera.sun_path, "gniazdo_serwera" );
    serwer_dlugosc = sizeof( adres_serwera );
    //Polaczenie gniazda klienta z gniazdem serwera
    test1 = connect( gniazdo_klienta,( struct sockaddr * ) & adres_serwera, serwer_dlugosc );
    if( test1 ==- 1 ) blad();
   
    //Komunikacja gniazda serwera z gniazdem klienta
    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 );
}
P-99377
DejaVu
» 2013-12-16 18:37:54
Nie poprawiłeś niczego z tego o czym pisałem.
P-99379
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.
P-99384
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.
P-99385
« 1 »
  Strona 1 z 1