Archiv verlassen und diese Seite im Standarddesign anzeigen : 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.
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,
_
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,
_
ok soweit habe ich das verstanden.
Nur was bewirkt / welchen nutzen hat es in diesem bestimmten fall?
soll ich den gesammten quelltext posten?
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
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);
}
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
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.
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 ;)
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.
Powered by vBulletin® Version 4.2.5 Copyright ©2025 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.