[C/C++] Problem mit select() unter C

Dieses Thema im Forum "Programmierung & Entwicklung" wurde erstellt von myth2806, 8. Dezember 2006 .

Schlagworte:
  1. 8. Dezember 2006
    Problem mit select() unter C

    Hi leutz,

    also ich wollte mir einen einfachen universalproxy proxy baun was mir anfangs nicht so ganz gelungen ist da ich die select-funkltion noch nicht kannte. Nachdem mich Kolazomai etwas beraten hat, wusste ich, dass ich diese funktion erwenden muss. KK also schnell gelernt wies geht nur leider funktioniert es nicht. er bleibt immer bei der select-anweisung stehen.

    hier der src:

    Code:
    #include <io.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <windows.h>
    #include <winsock.h>
    #include <winsock2.h>
    
    #define BUFFER_SIZE 4096
    #define LISTENING_PORT 7800
    #define ROUTING_PORT 80
    #define HOST_ADDR "72.14.221.99"
    
    int main()
    {
     WORD wVersionRequested;
     WSADATA wsaData;
     wVersionRequested = MAKEWORD (1, 1);
     if (WSAStartup (wVersionRequested, &wsaData) != 0)
     {
     printf( "[-] Error while init. Winsock\n");
     exit(0);
     }
     else
     {
     printf("[+] Winsock init.\n");
     }
    
     SOCKET clientsock;
     SOCKET serversock;
     
     clientsock = socket(AF_INET,SOCK_STREAM,0);
     serversock = socket(AF_INET,SOCK_STREAM,0);
     
     if ((clientsock == INVALID_SOCKET) || (serversock == INVALID_SOCKET))
     {
     printf ("[-] Error: socket()\n");
     perror("");
     exit(0);
     }
    
     struct sockaddr_in client;
     client.sin_family = AF_INET;
     client.sin_port = htons(LISTENING_PORT);
     client.sin_addr.s_addr = INADDR_ANY; 
     
     struct sockaddr_in server;
     server.sin_family = AF_INET;
     server.sin_port = htons(ROUTING_PORT);
     server.sin_addr.s_addr = inet_addr(HOST_ADDR);
     
     int tmp = 0;
     int client_size = sizeof(client);
     int c, socket_client_ds = clientsock, socket_server_ds = serversock;
     char* buffer;
     fd_set sockets;
     
     if (bind(clientsock,(struct sockaddr*)&client,sizeof(client))==SOCKET_ERROR)
     {
     close (clientsock);
     close (serversock);
     printf ("[-] Error: bind()\n");
     perror("");
     exit(0);
     }
     
     if (listen(clientsock,1)==SOCKET_ERROR)
     {
     close (clientsock);
     close (serversock);
     printf ("[-] Error: listen()\n");
     perror("");
     exit(0);
     }
     
     printf ("[+] Proxy running...\n\n----------\n\n");
     
     for (;;)
     {
     printf ("[+] Waiting for connection...\n");
     
     tmp = accept(clientsock,(struct sockaddr*)&client,&client_size);
     if (tmp == -1)
     {
     printf ("[-] Connectin failed!\n");
     continue;
     }
     printf ("[+] Incoming connection...\n");
     
     if (connect(serversock,(struct sockaddr*)&server,sizeof(server))==-1)
     {
     printf ("[-] Couldn'd establish connection to server!\n");
     continue;
     }
     while ((tmp=recv(serversock,buffer,sizeof(buffer)-1,0))>0)
     {
     buffer[tmp] = '\0';
     send (clientsock,buffer,strlen(buffer),0);
     memset(buffer,'\0',sizeof(buffer));
     }
     
     if (serversock>clientsock) { c = serversock; }
     else { c = clientsock; }
     
     printf ("%d,%d,%d\n",clientsock,serversock,c);
     
     for(;;)
     {
     FD_ZERO (&sockets);
     FD_SET (serversock,&sockets);
     FD_SET (clientsock,&sockets);
     // Hier bleibt er hängen
     select(c+1,&sockets,NULL,NULL,NULL);
     if (FD_ISSET(serversock,&sockets)>0)
     {
     tmp=recv(serversock,buffer,sizeof(buffer)-1,0);
     buffer[tmp] = '\0';
     if (tmp != SOCKET_ERROR)
     {
     send(clientsock,buffer,strlen(buffer),0);
     }
     memset(buffer,'\0',sizeof(buffer));
     }
     if (FD_ISSET(clientsock,&sockets)>0)
     {
     tmp=recv(clientsock,buffer,sizeof(buffer)-1,0);
     buffer[tmp] = '\0';
     if (tmp != SOCKET_ERROR)
     {
     send(serversock,buffer,strlen(buffer),0);
     }
     memset(buffer,'\0',sizeof(buffer));
     } 
     }
    
     printf ("[+] Client disconnected\n");
     }
     
     close (clientsock);
     close (serversock);
     
     return 0;
    }
    
    greez myth
     
  2. 8. Dezember 2006
    AW: Problem mit select() unter C

    Kannst du denn sicherstellen, dass einer der Sockets zu dem Zeitpunkt auch zu lesende Daten enthält? Ansonsten blockiert select() ja sowieso durch das NULL. Testhalber könntest du mit dem letzten Parameter mal ein Timeout einbauen und den nachfolgenden Codeblock über SOCKET_ERROR und select == 0 rausfiltern...
     
  3. 9. Dezember 2006
    AW: Problem mit select() unter C

    thx schonmal dafür!
    ich hab jetzt den code angepasst dass er 5 sekunden als timeout in der select-funktion hat. jetzt bleibt er zwar dort nicht mehr hängen allerdings kommt trotzdem nichts beim server an bzw beim client. also der proxy funzt nicht wenn ich ihn mal lokal laufen lasse und versuche ihn mit einem browser aufzurufen. joa da steht dann zwar immer schön dass ers nach 5 sekunden nochmal versucht aber der broser läd und läd und es kommt nix bei rum -.-

    thx aber schonmal!

    greez myth
     
  4. 9. Dezember 2006
    AW: Problem mit select() unter C

    Schmarre ...

    select() 'blockiert' nur solange, bis ein FD gesetzt ist. Und das ist ja das, was wir wollen. Mit Timeout wirds nur unnoetig performance-ziehend und macht man eigentlich nur, wenn man auf die Sockets nur durch Schleifen z.B. bei Arrays nicht richtig zugreifen kann.

    Also ist ein Timeout nicht sinnvoll, da es auch ohne gehen muesste und geht.

    Unter Windows ist der erste Parameter 0, und nicht der groesste FD + 1 !
    Ausserdem abfragen, ob select() einen Error zurueckgegeben hat.

    Mfg,

    Kolazomai
     
  5. 9. Dezember 2006
    AW: Problem mit select() unter C

    thx schonmal meinte auch sowas gelesen zu haben aber man ist ja um jede hilfe dankbar XD
    nur leider funktioniert es immer noch nicht. ich lasse jetzt abfragen ob der rückgabewert von select() SOCKET_ERROR ist und wenn ja halt genauere informationen per perror ausgeben lassen.
    naja jetzt hab ich das alte problem wieder dass er sich an der stelle "aufhängt".
    da wir ja jetzt wissen das select blockiert solang nichts zum abholen ist haben wir auch die ursache allerdings muss es etwas auf dem serversock zum abholen geben da ich ja den clientsock per browser aufrufen will und der serversock an einen webserver gerichtet ist. eigendlich sollte ja der HTTP-Request vom Client weitergeleitet werden und dann die Daten vom Webserver wieder zurück

    greez myth
     
  6. 9. Dezember 2006
    AW: Problem mit select() unter C

    Hi,

    du brauchst uebrigens 3 Sockets:

    1. Nimmt Connections an
    2. ClientSocket Nr. 1
    3. ClientSocket Nr. 2

    Hier mal ein 'einfaches' cross-platform select() -Beispiel von mir geschrieben:
    Code:
    /* Select Example
     by Kolazomai
     gcc select.c -o select -Wall -W -Werror */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    
    #ifdef _WIN32
    #include <windows.h>
    #include <winsock.h>
    #include <winsock2.h>
    #include <io.h>
    
    #else
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <sys/select.h>
    #include <arpa/inet.h>
    #include <netinet/in.h>
    #include <unistd.h>
    
    #endif
    
    #include <errno.h>
    
    
    #ifndef _WIN32
    typedef int socket_t;
    #define SOCKET_ERROR (-1)
    #define INVALID_SOCKET (-1)
    #define close_socket close
    
    #else
    typedef SOCKET socket_t;
    
    #endif
    
    
    #define MAX_BACKLOG 5
    #define MAX_BUF 1024
    #define _PORT_ 7999
    
    int main(void)
    {
     // Sockets
     socket_t bindfd;
     socket_t cliefd_1 = INVALID_SOCKET;
     socket_t cliefd_2 = INVALID_SOCKET;
    
     // Bind-Infos
     struct sockaddr_in addr;
    
     addr.sin_family = AF_INET;
     addr.sin_port = htons(_PORT_);
     addr.sin_addr.s_addr = inet_addr("0.0.0.0");
    
    
     // bindfd = socket
    
     bindfd = socket(AF_INET,SOCK_STREAM,0);
    
     if (bindfd == INVALID_SOCKET)
     {
     perror("socket()");
     return EXIT_FAILURE;
     }
    
    
     // bind()
    
     if (bind(bindfd,(struct sockaddr*)&addr,sizeof(addr)) == SOCKET_ERROR)
     {
     perror("bind()");
     return EXIT_FAILURE;
     }
    
    
     // listen()
    
     if (listen(bindfd,MAX_BACKLOG) == SOCKET_ERROR)
     {
     perror("listen()");
     return EXIT_FAILURE;
     }
    
    
     // vars fuer select()
     int action = 0;
     int max_int = 0;
     int rcv_int = 0;
     fd_set readfds;
     char buf[MAX_BUF];
    
     // unendlos-schleife mit select()
     for (;;)
     {
     FD_ZERO(&readfds);
    
     #ifndef _WIN32
     // Unix only - Rausfinden, was der hoechste FD ist
     if (bindfd > max_int)
     {
     max_int = bindfd;
     }
     if (cliefd_1 > max_int)
     {
     max_int = cliefd_1;
     }
     if (cliefd_2 > max_int)
     {
     max_int = cliefd_2;
     }
     #endif
    
     // socket, der connections annehmen soll, setzen
     FD_SET(bindfd,&readfds); 
     
     // clients setzen
     if (cliefd_2 != INVALID_SOCKET)
     {
     FD_SET(cliefd_2,&readfds);
     }
     if (cliefd_1 != INVALID_SOCKET)
     {
     FD_SET(cliefd_1,&readfds);
     }
    
    
     // select() starten
     #ifdef _WIN32
     action = select(0,&readfds,NULL,NULL,NULL);
     #else
     action = select(max_int+1,&readfds,NULL,NULL,NULL);
     #endif
    
     if (action == SOCKET_ERROR)
     {
     perror("select()");
     continue;
     }
    
    
     // schaun, was gesetzt ist
     if (FD_ISSET(bindfd,&readfds))
     {
     // irgendein client ist connected
     if (cliefd_1 == INVALID_SOCKET)
     {
     if ((cliefd_1 = accept(bindfd,NULL,0)) == INVALID_SOCKET)
     {
     perror("accept()");
     }
     else
     {
     printf("[+] Client_1\n");
     }
     }
     else if (cliefd_2 == INVALID_SOCKET)
     {
     if ((cliefd_2 = accept(bindfd,NULL,0)) == INVALID_SOCKET)
     {
     perror("accept()");
     }
     else
     {
     printf("[+] Client_2\n");
     }
     }
     else
     {
     // beide clienten besetzt
     printf("Beide Clienten besetzt\n");
     }
     }
     else
     {
     if (cliefd_1 != INVALID_SOCKET)
     {
     if (FD_ISSET(cliefd_1,&readfds))
     {
     rcv_int = recv(cliefd_1,buf,MAX_BUF - 1,0);
     
     if (rcv_int == SOCKET_ERROR || rcv_int == 0)
     {
     // disconnected
     printf("[-] Client\n");
     perror("recv()");
     close_socket(cliefd_1);
     cliefd_1 = INVALID_SOCKET;
     }
    
     buf[rcv_int] = '\0';
    
     printf("Client_1 said: \"%s\"\n",buf);
    
     // hier koenntest dus an cliefd_2 weitersenden, wenn er nicht auf 
     // invalid_socket gesetzt ist
     if (cliefd_2 != INVALID_SOCKET)
     {
     send(cliefd_2,buf,strlen(buf),0);
     }
     }
     }
     if (cliefd_2 != INVALID_SOCKET)
     {
     if (FD_ISSET(cliefd_2,&readfds))
     {
     rcv_int = recv(cliefd_2,buf,MAX_BUF - 1,0);
    
     if (rcv_int == SOCKET_ERROR || rcv_int == 0)
     {
     // disconnected
     printf("[-] Client\n");
     perror("recv()");
     close_socket(cliefd_2);
     cliefd_2 = INVALID_SOCKET;
     }
    
     buf[rcv_int] = '\0';
    
     printf("Client_2 said: \"%s\"\n",buf);
    
    
     if (cliefd_1 != INVALID_SOCKET)
     {
     send(cliefd_1,buf,strlen(buf),0);
     }
     }
     }
     }
     }
    
     return EXIT_SUCCESS;
    }
    Ich hoffe, das geht so ^^. Bei mir funktionierts grade schon, soweit ich das jetzt seh
    Das einzige, was noch nicht geht, ist, dass, wenn ein 3ter kommt, er rumspammt.
    Das muesste man vielleicht mit einem 4ten Socket loesen, der die Connection annimmt und gleich wieder schliesst.

    Greetz,

    Kolazomai
     
  7. Video Script

    Videos zum Themenbereich

    * gefundene Videos auf YouTube, anhand der Überschrift.