Programowanie gniazd BSD (lokalnie) pod Ubuntu: Bad file descriptor

Witam znalazłem przykładowy kod serwera i klienta w pewnym pdfie (zaznaczam, iż nie jest to moj program, lecz zapozyczony, jedynie w celu nauki). Jestem w tym zielony (zwlaszcza ze zaczynam prace z Ubuntu), i chciałbym po prostu sprawdzić jak działa stworzony program, jednak po probie wyslania pakietu do serwera w terminalu wyswietla sie blad: Bad file descriptor.

 

Czy mógłby mi pomoc ktos pomóc, kto miał do czynienia z programowaniem sieciowym?

 

serwer:

#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <sys/un.h>
#include <unistd.h>
#include <stdlib.h>
void blad()
{
perror("Blad serwera. test1 tworzenie gniazda socket");
exit(1);
}
void blad1()
{
perror("Blad serwera. Blad przy bind/n");
exit(1);
}
void blad2()
{
perror("Blad serwera. Przy nasluchiwaniu/n");
exit(1);
}
void blad3()
{
perror("Blad serwera.Przy czytaniu read \n");
exit(1);
}
void blad4()
{
perror("Blad serwera.Przy odpisywaniu /n");
exit(1);
}

int main()
{
    int gniazdo_serwera;
    int gniazdo_dla_klienta;
    int serwer_dlugosc;
    int klient_dlugosc;
    int test1,test2,test3,test4,test5;
    char znak;
    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) blad1();

    //Utworzenie kolejki dla oczekujacych polaczen
    test3=listen(gniazdo_serwera,5);
    if (test3==-1) blad2();
    printf("Serwer nasluchuje...\n");

    bool q=true;

    //Komunikacja gniazda serwera z gniazdem klienta
    while(1)
    {
        //Przyjęcie polaczenia przez gniazdo serwera
        gniazdo_dla_klienta=accept(gniazdo_serwera,(struct sockaddr *)&adres_klienta,(socklen_t *)&klient_dlugosc);
        test4=read(gniazdo_dla_klienta,&znak,2);

        if (test4>0) printf("Odebralem do klienta znak %c.\n",znak);
        else blad3();

        znak='b';

        test5=write(gniazdo_dla_klienta,&znak,1);
        if (test5>0) {printf("Wysylam dane do klienta znak %c.\n",znak);q=false;}
        else blad4();


        if(!q)close(gniazdo_dla_klienta);
    }
    close(gniazdo_serwera);
    exit(0);
}

//klient

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <sys/un.h>
#include <unistd.h>
#include <stdlib.h>
void blad()
{
perror("Blad klienta. Tworzenie gniazda socket");
exit(1);
}
void blad2()
{
perror("Blad klienta. Laczenie connect");
exit(1);
}
void blad3()
{
perror("Blad klienta. komunikacja write");
exit(1);
}
void blad4()
{
perror("Blad klienta. komunikacja read");
exit(1);
}

int main()
{
int gniazdo_klienta;
int serwer_dlugosc;
char znak;
int test1,test2,test3,test4,test5;
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) blad2();
znak='a';
//Komunikacja gniazda serwera z gniazdem klienta
test4=write(gniazdo_klienta,&znak,1);
if (test4>0) printf("Wyslalem do serwera znak %c.\n",znak);
else blad();
test5=read(gniazdo_klienta,&znak,1);
if (test5>0) printf("Otrzymalem do serwera znak %c.\n",znak);
else blad();
close(gniazdo_klienta);
exit(0);
}

U mnie działa, przykład:

/home/tomek/roboczy/prog/ks$ ./server
Serwer nasluchuje...
Odebralem do klienta znak a.
Wysylam dane do klienta znak b.
Odebralem do klienta znak a.
Wysylam dane do klienta znak b.
Odebralem do klienta znak a.
Wysylam dane do klienta znak b.

/home/tomek/roboczy/prog/ks$ ./klient
Wyslalem do serwera znak a.
Otrzymalem do serwera znak b.
/home/tomek/roboczy/prog/ks$ ./klient
Wyslalem do serwera znak a.
Otrzymalem do serwera znak b.

 

Ale jeśli chodzi o kod źródłowy to jest on bardzo słabej jakości.

ok, tlyko u mnie naprawde nie działa i nie moge odnaleźć tej przyczyny. wszystkie pliki mam w jednym katalogu kompiluja sie oba (co prawda sa nie znaczace warningi) ale wystepuje blad tak jak na załączonym obrazu:

 

http://fotowrzut.pl/KPJRUYA36X

 

dodam, że Ubuntu mam postawione na virtualboxie (jeśli to ma wpływ na cokolwiek)

Skoro read zgłasza że ma nieprawidłowy deskryptor to sprawdź co wyjdzie z funkcji accept, dodatkowo ostatni argument dla funkcji accept nie jest ustawiony (powinna to być maksymalna wielkość bufora tak aby funkcja accept wiedziała ile może tam zapisać).

 

Zmień wewnętrzną pętlę w serwerze na coś takiego:

//Komunikacja gniazda serwera z gniazdem klienta
    while(1)
    {
	klient_dlugosc = sizeof(sockaddr_un);
        gniazdo_dla_klienta=accept(gniazdo_serwera,(struct sockaddr *)&adres_klienta,(socklen_t *)&klient_dlugosc);

	if( gniazdo_dla_klienta < 0 )
	{
		printf("ups: %d\n", errno);
		exit(1);
	}

        test4=read(gniazdo_dla_klienta,&znak,1);

        if (test4>0) printf("Odebralem do klienta znak %c.\n",znak);
        else blad3();

        znak='b';

        test5=write(gniazdo_dla_klienta,&znak,1);
        if (test5>0) {printf("Wysylam dane do klienta znak %c.\n",znak);q=false;}
        else blad4();


        if(!q)close(gniazdo_dla_klienta);
    }

Zauważ też że w swoim kodzie wołałeś read z długością bufora ustawioną na 2 a buforem był char czyli jeden bajt.

Dziekuję pięknie za odpowiedź, błędem było brak:

 

klient_dlugosc = sizeof(sockaddr_un);

 

 

A czy nie jest tak, że rozmiar bufora może być większy od przyjmowanych danych ?

 

Rozmiar bufora może być większy natomiast w twoim przypadku jest on mniejszy, buforem jest jeden znak a pozwalasz funkcji read na zapisanie dwóch znaków.

 

Rozumiem. Dziękuje jeszcze raz za pomoc.