select() für dumme
-
Original erstellt von Doktor Prokt:
**Das muss nach Linux, select() gibts in Standard C++ nicht.
**jup
Thread verschoben ins Unix Forum.
-
Warum klappt das nich:
anfang des codes:
#include <winsock.h> #include <stdio.h> #include <conio.h> #define MAXCLIENTS 10 #define BUFFERSIZE 1024 struct user{ char name[50]; int socket; user *prev; user *next; }; user server; int user_nr=0; char buffer[BUFFERSIZE];
und die funktion mit select:
int interchange(void) { fd_set fds; FD_ZERO(&fds); struct timeval tv; tv.tv_sec=5; tv.tv_usec=0; user *p=&server; while(p->next!=NULL); { p=p->next; FD_SET(p->socket,&fds); select(MAXCLIENTS+1,&fds,NULL,NULL,&tv); recv(p->socket,buffer,sizeof(BUFFERSIZE)-1,0); if(FD_ISSET(p->socket,&fds)) { printf("\ngelesen\n"); }else printf("\n timeout\n"); } return 0; }
Er bleibt immer beim recv hängen.
PS. lasst euch von dem ganzen drum herrum nich verwirren.[ Dieser Beitrag wurde am 03.11.2002 um 20:14 Uhr von TheDeath editiert. ]
-
Ist doch klar, daß er hängen bleibt:
recv() wartet so lange, bis es was received.
recv() darf erst NACH der Abfrage if(FD_ISSET(...)) aufgerufen werden. Dann funktioniert es. Es muss also im if-Block stehen.
-
So? geht immer noch nich, bleibt nach dem aufruf der schleife hänge, also er gibt auf dem monitor "schleife beginnt" aus und macht dann nix mehr.
int interchange(void) { fd_set fds; FD_ZERO(&fds); struct timeval tv; tv.tv_sec=5; tv.tv_usec=0; user *p=&server; printf("schleife beginnt\n"); while(p->next!=NULL); { p=p->next; FD_SET(p->socket,&fds); select(MAXCLIENTS+1,&fds,NULL,NULL,&tv); printf("select ok"); if(FD_ISSET(p->socket,&fds)) { recv(p->socket,buffer,sizeof(BUFFERSIZE)-1,0); printf("\ngelesen\n"); }else printf("\n timeout\n"); } return 0; }
-
Hm, jo, select() darfst du natürlich nur einmal aufrufen.
Versuchs mal so:
int interchange(void) { int i; fd_set fds; FD_ZERO(&fds); struct timeval tv; tv.tv_sec=5; tv.tv_usec=0; user *p=&server; printf("schleife beginnt\n"); while(p->next!=NULL); { p=p->next; FD_SET(p->socket,&fds); } select(MAXCLIENTS+1,&fds,NULL,NULL,&tv); printf("select ok"); for (i = 0; i <= MAXCLIENTS; i++) { if(FD_ISSET(i,&fds)) { recv(i,buffer,sizeof(BUFFERSIZE)-1,0); printf("\ngelesen\n"); } } return 0; }
So sollte es funktionieren.
-
klappt immer noch nich, der mag das select nich, die schleife startet er ganz normal nur kommt dann KEINE meldung das select ausgeführt wurde.
achja, das programm soll für windows sein, kann es sein das die funktion da nich funktioniert?
-
Hm, keine Ahnung, wusste bis gestern gar nicht, daß es select() auch für Windows gibt. Auf jeden Fall sollte er "select ok" spätestens nach deiner vereinbarten TimeOut-Zeit ausführen. Das einzige, was ich mir noch vorstellen kann, ist, daß du vor dem Aufruf der Funktion interchange() eine andere Funktion aufrufst, die das Programm blockiert und auf irgendwas wartet. Oder es kann sein, daß die Liste falsch implmentiert ist und er keinen Pointer mit dem Wert NULL findet...
Poste einfach mal mehr Code, dann finden mer das schon raus.
-
**
achja, das programm soll für windows sein, kann es sein das die funktion da nich funktioniert?
**
Vieles funktioniert unter Windows nicht... aber "select" sollte schon gehenWas für ein Return-Wert kriegst du eigentlich von select?
Ohne errno oder return-Wert weist du nicht ob das geklappt hat...
-
Ich pack das mal in das WinAPI Forum, wenn es um Windos geht, da die WinAPI Socket Unterstützung doch sehr simpel und primitiv ist im Gegensatz zu den POSIX Sockets und du sicher mit anderen Problemen kämpfen musst.
hier sind ein paar Links, die dir sicher helfen (sind aber für Unix)
http://www.acme.com/software/thttpd/ <-- Beispiel Programm
@Doktor
select muss man doch eigentlich in die Schleife packen! Wie soll select sonst die Bitmaske setzen?[ Dieser Beitrag wurde am 04.11.2002 um 20:31 Uhr von kingruedi editiert. ]
-
Original erstellt von kingruedi:
**@Doktor
select muss man doch eigentlich in die Schleife packen! Wie soll select sonst die Bitmaske setzen?
**Nein, select() für jedes Socket aufzurufen, wäre unsinnig. Die stehen doch alle im fd_set, das an select() übergeben wird.
Falls du aber bei Servern die Hauptschleife meinst, die immer durchlaufen wird, steht select() natürlich schon in einer Schleife
-
das MAXCLIENTS kannste nicht verwenden. koennte schliesslich sein, dass die zugewiesene socketdeskriptoren einen groesseren wert haben. musst das maximum aller sockets bestimmen. auch die for(i=0;i<=MAXCLIENTS;++i){} schleife ist demnach falsch, da z.b. i=0 normalerweise stdin ist. hat die linked list auch gueltige sockets? ansonsten scheints eigentlich richtig zu sein, aber von win hab ich keine ahnung, vielleicht muss man da mehr machen.
-
hier is mal mein completter code, ich hab festgestellt, das der fehler irgendwo in der ersten schleife bei interchange() liegt, weis aber nich warum.
#include <winsock.h> #include <stdio.h> #include <conio.h> #define MAXCLIENTS 10 #define BUFFERSIZE 1024 struct user{ char name[50]; int socket; user *prev; user *next; }; int adduser(char name[50],int socket); int interchange(void); user* prev(void); int ausgabe(void); int loeschen(void); user server; int user_nr=0,max_sock=0; char buffer[BUFFERSIZE]; int main(int argc, char *argv[]) { server.next=NULL; server.prev=NULL; char name[50]; int cli_size, bytes,s,c,retval; WSADATA wsa; fd_set fds; struct sockaddr_in cli; struct sockaddr_in serv; serv.sin_addr.s_addr=INADDR_ANY; serv.sin_port=htons(80); serv.sin_family=AF_INET; char willkomm[]="Willkommenn auf dem Chat-Server\r\n"; FILE *log; log=fopen("log.txt","w"); fprintf(log,"This file was build by chat_srv\n\n"); //WSA initialisieren if(WSAStartup(MAKEWORD(1,1),&wsa)) { fprintf(log,"WSAStartup() failed %lu\n",(unsigned long)GetLastError()); return EXIT_FAILURE; }else fprintf(log, "WSAStartup() successful started\n"); //################### //socket erstellen if((s=socket(AF_INET,SOCK_STREAM,0))==-1) { fprintf(log,"Error, creating socket failed\n"); }else fprintf(log,"Socket successful created\n"); //################### //port an locale ip binden if(bind(s,(struct sockaddr *)&serv,sizeof(serv)) ==-1) { fprintf(log,"Couldn't bind port %i to lokalhost\n",s); }else fprintf(log,"Port %i successful bound to localhost\n",s); //################## //socket für verbindungen öffnen if(listen(s,4)==-1) { fprintf(log,"Couldn't open socket for Client connections"); }else fprintf(log,"Port successful for Client-Connections opened"); //################## cli_size=sizeof(cli); for(;;) { FD_ZERO(&fds); FD_SET(s,&fds); if(user_nr<MAXCLIENTS) { if(FD_ISSET(s,&fds)) { if((c=accept(s,(struct sockaddr*)&cli,&cli_size))==-1) { printf("Error, accept"); return -1; } if((bytes=recv(c,name,50,0))==-1) { printf("Error, name"); return -1; } name[bytes]='\0'; adduser(name,c); printf("neuer user: %s\nEs sind jetzt %i User auf dem Server",name, user_nr); interchange(); printf("\ninterchange ende\n"); } } } } int adduser(char *name, int socket) { int bytes; user_nr++; // zeiger auf neuen user namens client definieren user *client=new user; //z auf den letzten user setzen user *z=prev(); //neue strukur füllen strcpy(client->name,name); client->socket=socket; client->next=NULL; //der nachvolger von letzten user wird auf den neuen gesetzt z->next=client; // der vorgänger der neuen wird auf den zeiger der letzten gesetzt client->prev=z; char user[100]; sprintf(user,"%i",user_nr); if((bytes=send(socket,user,sizeof(user),0))==-1) { printf("slkjf"); } printf("\ngesendet\n"); return 0; } user *prev(void) { user *p=&server; while(p->next!=NULL) { if(p->socket>max_sock) max_sock=p->socket; p=p->next; } return p; } int interchange(void) { int i; fd_set fds; FD_ZERO(&fds); struct timeval tv; tv.tv_sec=5; tv.tv_usec=0; user *p=&server; printf("\nschleife beginnt\n"); while(p->next!=NULL) { p=p->next; FD_SET(p->socket,&fds); } printf("schleife ende\n"); select(max_sock+1,&fds,NULL,NULL,&tv); printf("select ok"); for (i = 0; i <= MAXCLIENTS; i++) { if(FD_ISSET(i,&fds)) { recv(i,buffer,sizeof(BUFFERSIZE)-1,0); printf("\ngelesen\n"); }else printf("\n timeout \n"); } return 0; }
-
kann mir denn keiner helfen?
-
du rufst prev() auf, wenn die neue verbindung noch nicht in der linked list verkettet ist, demnach wird diese verbindung bei der berechnung von max_sock auch nicht beruecksichtigt.
wie das unter win ist weiss ich nicht, aber unter unix sollte man ausserdem den rueckgabewert von select() ueberpruefen und im falle von -1 die externe variable errno mit EINTR vergleichen.
auch solltest du ueberpruefen, ob der log pointer, der auf eine FILE struktur zeigt, gueltig ist.