Anzeige:
Ergebnis 1 bis 11 von 11

Thema: Stdin_fileno

  1. #1
    Registrierter Benutzer
    Registriert seit
    02.11.2004
    Beiträge
    22

    Stdin_fileno

    Hallo

    Hab eine Verständnissfrage.
    Ich versuche gerade den Quelltext von zotteljedis select Servers zu verstehen. http://www.zotteljedi.de/doc/socket-tipps/

    Da ist eine Stelle mit der ich garnichts anfangen kann. Ist bestimmt nicht so schwehr aber bei google hab ich nix darüber gefunden.

    Code:
    add_client(&list, STDIN_FILENO);
    Code:
    int add_client(struct list_type *list, int sock)
    {
    	struct list_entry *n;
    
    	n = malloc(sizeof(*n));
    	if (!n)
    	{
    		perror("malloc() failed");
    		return 1;
    	}
    
    	n->sock = sock;
    	n -> next = list->data;
    
    	list->data = n;
    	list->count++;
    
    	return 0;
    }
    mich würde jetzt mal Interessieren für was STDIN_FILENO da ist und was es bewirkt.

  2. #2
    Administrator Avatar von anda_skoa
    Registriert seit
    17.11.2001
    Ort
    Graz, Österreich
    Beiträge
    5.477
    Das ist der Filedescriptor des Standardinputs des Programms.

    Ciao,
    _
    Qt/KDE Entwickler
    Debian Benutzer

  3. #3
    Registrierter Benutzer
    Registriert seit
    02.11.2004
    Beiträge
    22
    Was doch im Normalfall die Tastatur ist oder?
    Oder kann man den irgendwie umstellen?

    Ich verstehe den Zusammenhang an dieser Stelle nicht.

    Ich stehe mir da gerade böse auf dem Schlauch denk ich.
    Geändert von Primex (16-06-2005 um 15:03 Uhr)

  4. #4
    Administrator Avatar von anda_skoa
    Registriert seit
    17.11.2001
    Ort
    Graz, Österreich
    Beiträge
    5.477
    Ein Prozess hat standardmäßig drei Filedescriptoren/Dateiströme:
    Eingabe (stdin)
    Ausgabe (stdout)
    und
    Fehler (stderr)

    Wenn ein Prozess von der Konsole gestart wird, sind diese mit der Konsole verbunden, d.h. Eingaben des Benutzer gehen in den Prozess, seine Ausgaben (beide) kommen auf den Schirm.

    Man kann zB den Output- oder Errorstrem eines anderen Prozesses in den Input eines zweiten Prozesses umleiten
    #> echo "foo" | wc

    Normalerweise sind die drei Descriptoren die ersten drei, als 0, 1 und 2, aber besser man arbeitet mir den Konstanten wie die, die du gefunden hast.
    Die Descriptoren braucht man nur, wenn man Funktionen aufrufen will, die eben solche erwarten.
    Andere Funktione erwarten vielleich einen FILE Pointer und für die drei wichtigen gibt es da auch schon "Namen"
    stdin, stdout, stderr

    Ciao,
    _
    Qt/KDE Entwickler
    Debian Benutzer

  5. #5
    Registrierter Benutzer
    Registriert seit
    02.11.2004
    Beiträge
    22
    ok soweit habe ich das verstanden.
    Nur was bewirkt / welchen nutzen hat es in diesem bestimmten fall?

    soll ich den gesammten quelltext posten?

  6. #6
    Registrierter Benutzer Avatar von klewan
    Registriert seit
    06.05.2005
    Ort
    Wien
    Beiträge
    99
    post mal den gesamten code!

    aber ich denke das es sich um nen server handelt der pro client einen prozess forkt mit dup2() den socket auf stdin des gforkten prozesse umbiegt.


    z.b.: xinet und inetd machen dies so

  7. #7
    Registrierter Benutzer
    Registriert seit
    02.11.2004
    Beiträge
    22
    Ok Hier mal den gesammten Code.
    Nein kein fork. Es wird über select geregelt!

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/fcntl.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    
    #include <sys/socket.h>
    #include <unistd.h>
    
    struct list_entry {
    	int			sock;
    	struct list_entry	*next;
    };
    
    struct list_type {
    	struct list_entry	*data;
    	unsigned		count;
    };
    
    #define BUF_SIZ	4096
    #define PORT 7000
    
    void init_list(struct list_type *list)
    {
    	list->data = NULL;
    	list->count = 0;
    }
    
    int add_client(struct list_type *list, int sock)
    {
    	struct list_entry *n;
    
    	n = malloc(sizeof(*n));
    	if (!n)
    	{
    		perror("malloc() failed");
    		return 1;
    	}
    
    	n->sock = sock;
    	n -> next = list->data;
    
    	list->data = n;
    	list->count++;
    
    	return 0;
    }
    
    int remove_client(struct list_type *list, int sock)
    {
    	struct list_entry *lz, *lst = NULL;
    
    	if (!list->count)
    		return 1;
    
    	for (lz = list->data; lz; lz = lz->next)
    	{
    		if (lz->sock == sock)
    			break;
    		lst = lz;
    	}
    
    	if (!lz)
    		return 1;
    
    	if (lst)
    		lst->next = lz->next;
    	else
    		list->data = lz->next;
    
    	free(lz);
    	list->count--;
    
    	return 0;
    }
    
    int fill_set(fd_set *fds, struct list_type *list)
    {
    	int max = 0;
    	struct list_entry *lz;
    
    	for (lz = list->data; lz; lz = lz->next)
    	{
    		if (lz->sock > max)
    			max = lz->sock;
    		FD_SET(lz->sock, fds);
    	}
    
    	return max;
    }
    
    int get_sender(fd_set *fds)
    {
    	int i = 0;
    
    	while(!FD_ISSET(i, fds))
    		i++;
    
    	return i;
    }
    
    /* Sonderfall: STDIN_FILENO muss natuerlich auf STDOUT_FILENO
     * beschrieben werden.
     */
    int send_all(char *msg, int len, struct list_type *list, int sender)
    {
    	struct list_entry *lz;
    
    	for (lz = list->data; lz; lz = lz->next)
    	{
    		if (lz->sock == sender)
    			continue;
    
    		if (lz->sock == STDIN_FILENO)
    			write(STDOUT_FILENO, msg, len);
    		else
    			write(lz->sock, msg, len);
    	}
    
    	return 0;
    }
    
    int main_loop(int s)
    {
    	int c, max, sender, bytes;
    	fd_set fds;
    	struct list_type list;
    	char buf[BUF_SIZ];
    
    	init_list(&list);
    	add_client(&list, STDIN_FILENO);
    
    	for(;;)
    	{
    		FD_ZERO(&fds);
    		max = fill_set(&fds, &list);
    
    		FD_SET(s, &fds);
    		if (s > max)
    			max = s;
    
    		select(max + 1, &fds, NULL, NULL, NULL);
    
    		if (FD_ISSET(s, &fds))
    		{
    			c = accept(s, NULL, 0);
    			add_client(&list, c);
    		}
    		else
    		{
    			sender = get_sender(&fds);
    			bytes = read(sender, buf, sizeof(buf));
    			if (bytes == 0)
    				remove_client(&list, sender);
    			else
    				send_all(buf, bytes, &list, sender);
    		}
    	}
    }
    
    int main(void)
    {
    	int s;
    	struct sockaddr_in addr;
    	
    	s = socket(PF_INET, SOCK_STREAM, 0);
    	if (s == -1)
    	{
    		perror("socket() failed");
    		return 1;
    	}
    
    	addr.sin_addr.s_addr = INADDR_ANY;
    	addr.sin_port = htons(PORT);
    	addr.sin_family = AF_INET;
    
    	if (bind(s, (struct sockaddr*)&addr, sizeof(addr)) == -1)
    	{
    		perror("bind() failed");
    		return 2;
    	}
    
    	if (listen(s, 3) == -1)
    	{
    		perror("listen() failed");
    		return 3;
    	}
    
    	return main_loop(s);
    }

  8. #8
    Registrierter Benutzer Avatar von klewan
    Registriert seit
    06.05.2005
    Ort
    Wien
    Beiträge
    99
    hmm wo is das problem nochmal :-) ?


    anscheinend wird der main socket, listener auf STDIN umgebogen, eventuel quasi als admin console socket oder so , den alle andren clients bekommen eh den socket als FD

    lg

  9. #9
    Registrierter Benutzer
    Registriert seit
    02.11.2004
    Beiträge
    22
    eh ja ich denke ich sollte mich wohl noch etwas mit system/netzwerk programmierung auseinandersetzten.

    Werde aus diesem Code nicht schlau.
    Ich wollte einfach nur ein Server schreiben der mit hilfe von select mehrere Clients behandelt.

  10. #10
    Registrierter Benutzer Avatar von klewan
    Registriert seit
    06.05.2005
    Ort
    Wien
    Beiträge
    99
    der oben gennante code kann genau das


    aber ähhhm select is mit langsamen und vielen connections fast unpackbar :-D

    lieber pthread und mit mutexen syncen

  11. #11
    Registrierter Benutzer
    Registriert seit
    02.11.2004
    Beiträge
    22
    ja das weiß ich ja!

    es geht einfach nur um nen kleinen chat. Und da schreiben einige Leute es wäre besser mit select.

    Mir gings halt nur darum in die Materie einzusteigen.
    Ich hab hier ein Funktionierenden der hzalt nur mit einen Client umgehen kann. Den wollt ich jetzt interessehalber erweitern.

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •