PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Stdin_fileno



Primex
16-06-2005, 12:39
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.


add_client(&list, STDIN_FILENO);


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.

anda_skoa
16-06-2005, 14:22
Das ist der Filedescriptor des Standardinputs des Programms.

Ciao,
_

Primex
16-06-2005, 14:40
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.

anda_skoa
16-06-2005, 20:23
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,
_

Primex
16-06-2005, 20:42
ok soweit habe ich das verstanden.
Nur was bewirkt / welchen nutzen hat es in diesem bestimmten fall?

soll ich den gesammten quelltext posten?

klewan
16-06-2005, 22:25
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

Primex
17-06-2005, 15:41
Ok Hier mal den gesammten Code.
Nein kein fork. Es wird über select geregelt!


#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);
}

klewan
17-06-2005, 15:52
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

Primex
17-06-2005, 16:55
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.

klewan
17-06-2005, 17:14
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 ;)

Primex
17-06-2005, 17:20
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.