Thread: Shouldn't this code work? (select())

  1. #1
    Registered User
    Join Date
    Mar 2009
    Posts
    76

    Post Shouldn't this code work? (select())

    Shouldn't this code work? (select())

    Well, this is basically a proxy.
    It takes things from a program that is running on port 15777 and the puts it out to host on port 15776, but sence I added the
    select() witch is needed. It hasn't been working right. Any help?

    Code:
    #include <windows.h> //Required for socket init
    #include <iostream>
    #include <sys/time.h>
    using namespace std;
    int main(){
        
    
     
    
        
        char buf[256];
        char uua[256];
    WSAData wsdata; //Declare WSAData
    WORD wsver=MAKEWORD(2, 0); //We want Winsock 2.0
    WSAStartup(wsver, &wsdata);
    //WSA starting code
    
     
    
     
    
    //Hosting thing.
    
    
    SOCKET Szocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);  
     SOCKADDR_IN serverInf;
     serverInf.sin_family=AF_INET;
     serverInf.sin_addr.s_addr=INADDR_ANY;
     serverInf.sin_port=htons(15776);   
        bind(Szocket,(SOCKADDR*)(&serverInf),sizeof(serverInf));
     listen(Szocket,1);   
     SOCKET TempSock=SOCKET_ERROR;
     while(TempSock==SOCKET_ERROR)
     {
      std::cout<<"Waiting for incoming connections...\r\n";
      TempSock=accept(Szocket,NULL,NULL);
     }
     u_long iMode=1;
     ioctlsocket(Szocket,FIONBIO,&iMode);
     Szocket=TempSock;
     std::cout<<"Client connected!\r\n\r\n"; 
     
     
     
    
     
     
     
     
     
    SOCKET kSock=socket(AF_INET, SOCK_STREAM, 0);
    sockaddr_in sin;
    sin.sin_port=htons(15777); //Connect to port 15777
    sin.sin_addr.s_addr=inet_addr("127.0.0.1"); //Connect to localhost
    sin.sin_family=AF_INET;
    ioctlsocket(Szocket,FIONBIO,&iMode);
    if(connect(kSock,(sockaddr*)&sin, sizeof(sin)) == SOCKET_ERROR){ //Check the condition
    std::cout<<"Connect failed, error: "<<WSAGetLastError(); //Returns error code
    WSACleanup(); //Cleanup the library
    std::string lisquit;
    std::cin>>lisquit;
    }
    std::cout<<"Connection successful!\n";
     
    
    timeval tiz;
    tiz.tv_sec = 1;
    tiz.tv_usec = 0;
    
    FD_SET OrigMC;
    FD_SET PrxMC;
    
    
    
    
    //while (true){
    
    FD_ZERO(&OrigMC);
    FD_ZERO(&PrxMC);
    FD_SET(Szocket,&PrxMC);
    FD_SET(kSock,&OrigMC);
    
    
    cout<<"Loop started.\n";
    
    
    
    int selecta = select(0,&PrxMC,NULL,NULL,&tiz);
    cout<<"Has ready to recive: "<<selecta<<"\n";
    
    //if(selecta == 1){
    recv(Szocket,uua,sizeof(uua),0);    //Recive from my proxy server
    send(kSock,uua,sizeof(uua),0);      //Send to the real one
    cout<<"In:    "<<uua<<"\n\n";       //Echo it
    //}
       
    int selectb = select(0,&OrigMC,NULL,NULL,&tiz);
    cout<<"Has ready to recive: "<<selectb<<"\n";
    
    if(selectb == 1){
    recv(kSock, buf, sizeof(buf), 0);   //Recive from the real server
    send(Szocket,buf,sizeof(buf),0);    //Send to the proxy server
    cout<<"Out:    "<<buf<<"\n\n";      //Echo what it just recived and sent
    }
    
    //No more sleep?
    Sleep(50);
    //      Azjherben.org
    
    
    //}
    
     
    
     
    
    }

  2. #2
    Registered User
    Join Date
    Mar 2009
    Posts
    76
    This code works good on the first recive and send and recive and send but then starts echoing out 1's and -1's really fast I guess it also disconnects from the client. If I try to make it cout what it is sending/reciving it makes alot of beeping sounds.


    Code:
    #include <windows.h> //Required for socket init
    #include <iostream>
    #include <sys/time.h>
    using namespace std;
    int main(){
        
    
     
    
        
        char buf[256];
        char uua[256];
    WSAData wsdata; //Declare WSAData
    WORD wsver=MAKEWORD(2, 0); //We want Winsock 2.0
    WSAStartup(wsver, &wsdata);
    //WSA starting code
    
     
    
     
    
    //Hosting thing.
    
    
    SOCKET Szocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);  
     SOCKADDR_IN serverInf;
     serverInf.sin_family=AF_INET;
     serverInf.sin_addr.s_addr=INADDR_ANY;
     serverInf.sin_port=htons(15776);   
        bind(Szocket,(SOCKADDR*)(&serverInf),sizeof(serverInf));
     listen(Szocket,1);   
     SOCKET TempSock=SOCKET_ERROR;
     while(TempSock==SOCKET_ERROR)
     {
      std::cout<<"Waiting for incoming connections...\r\n";
      TempSock=accept(Szocket,NULL,NULL);
     }
     u_long iMode=1;
     //ioctlsocket(Szocket,FIONBIO,&iMode);
     Szocket=TempSock;
     std::cout<<"Client connected!\r\n\r\n"; 
     
     
     
    
     
     
     
     
     
    SOCKET kSock=socket(AF_INET, SOCK_STREAM, 0);
    sockaddr_in sin;
    sin.sin_port=htons(15777); //Connect to port 15777
    sin.sin_addr.s_addr=inet_addr("127.0.0.1"); //Connect to localhost
    sin.sin_family=AF_INET;
    //ioctlsocket(Szocket,FIONBIO,&iMode);
    if(connect(kSock,(sockaddr*)&sin, sizeof(sin)) == SOCKET_ERROR){ //Check the condition
    std::cout<<"Connect failed, error: "<<WSAGetLastError(); //Returns error code
    WSACleanup(); //Cleanup the library
    std::string lisquit;
    std::cin>>lisquit;
    }
    std::cout<<"Connection successful!\n";
     
    
    timeval tiz;
    tiz.tv_sec = 1;
    tiz.tv_usec = 0;
    
    FD_SET OrigMC;
    FD_SET PrxMC;
    
    
    
    
    //while (true){
    
    FD_ZERO(&OrigMC);
    FD_ZERO(&PrxMC);
    FD_SET(Szocket,&PrxMC);
    FD_SET(kSock,&OrigMC);
    
    
    cout<<"Loop started.\n";
    
    while (true)
    {
    int selecta = select(0,&PrxMC,NULL,NULL,&tiz);
    cout<<"Has ready to recive: "<<selecta<<"\n";
    
    if ( selecta >= 1 )
    {
       if( FD_ISSET( Szocket, &PrxMC ))
           {
                     recv(Szocket, buf, sizeof(buf), 0);  
                     send(kSock,buf,sizeof(buf),0);    
           }
    }
       
    
    
    
    int selectb = select(0,&OrigMC,NULL,NULL,&tiz);
    cout<<"Has ready to recive: "<<selectb<<"\n";
    
    if ( selectb >= 1 )
    {
       if( FD_ISSET( kSock, &OrigMC ))
           {
                     recv(kSock, buf, sizeof(buf), 0);  
                     send(Szocket,buf,sizeof(buf),0);    
           }
    }
    
    //No more sleep?
    Sleep(50);
    //      Azjherben.org
    
    
    }
    
     
    
     
    
    }

  3. #3
    int x = *((int *) NULL); Cactus_Hugger's Avatar
    Join Date
    Jul 2003
    Location
    Banks of the River Styx
    Posts
    902
    1) Indent your code.
    2) You don't capture the return value of recv(), so you are send()-ing the incorrect amount a line later. And vice-versa.
    3) You only need 1 call to select. Merge the two.
    4) Your sockets should be non-blocking.
    Last edited by Cactus_Hugger; 07-18-2009 at 10:05 AM.
    long time; /* know C? */
    Unprecedented performance: Nothing ever ran this slow before.
    Any sufficiently advanced bug is indistinguishable from a feature.
    Real Programmers confuse Halloween and Christmas, because dec 25 == oct 31.
    The best way to accelerate an IBM is at 9.8 m/s/s.
    recursion (re - cur' - zhun) n. 1. (see recursion)

  4. #4
    Registered User
    Join Date
    Mar 2009
    Posts
    76
    Quote Originally Posted by Cactus_Hugger View Post
    1) Indent your code.
    2) You don't capture the return value of recv(), so you are send()-ing the incorrect amount a line later. And vice-versa.
    3) You only need 1 call to select. Merge the two.
    4) Your sockets should be non-blocking.


    @1. Fine.
    @2. I'll post code soon, tell me if I did it right.
    @3. How do I merge.
    @4. They were.



    @ 2. Again: Is this what you mean?:

    Code:
    int selecta = select(0,&PrxMC,NULL,NULL,&tiz);
    cout<<"(PRX) Has ready to recive: "<<selecta<<"\n";
    
    if ( selecta >= 1 )
    {
       if( FD_ISSET( Szocket, &PrxMC ))
           {
                     recv(Szocket, buf, sizeof(buf), 0);  
                     char *orgbuf;
                     orgbuf = buf;
                     send(kSock,orgbuf,sizeof(orgbuf),0);    
           }
    }
       
    
    
    
    int selectb = select(0,&OrigMC,NULL,NULL,&tiz);
    cout<<"(ORG) Has ready to recive: "<<selectb<<"\n";
    
    if ( selectb >= 1 )
    {
       if( FD_ISSET( kSock, &OrigMC ))
           {
                     recv(kSock, buf, sizeof(buf), 0);  
                     char *prxbuf;
                     prxbuf = buf;
                     send(Szocket,prxbuf,sizeof(prxbuf),0);    
           }
    }
    Last edited by azjherben; 07-18-2009 at 11:09 AM.

  5. #5
    int x = *((int *) NULL); Cactus_Hugger's Avatar
    Join Date
    Jul 2003
    Location
    Banks of the River Styx
    Posts
    902
    @@1: Better.
    @@2: Nothing has changed...? More after:
    @@3:
    No, one call to select(). The whole _point_ of select is that you're passing multiple things to it.
    Code:
    fd_set my_fds;
    
    FD_ZERO(my_fds);
    FD_SET(kSock, &my_fds);
    FD_SET(Szocket, &my_fds);
    
    int select_ret;
    
    select_ret = select((kSock > Szocket ? kSock : Szocket) + 1, &my_fds, &my_fds, &my_fds, &tiz);
    if(select_ret > 0)
    {
        if(FD_ISSET(kSock, &my_fds))
        {
            // kSock is ready... attempt reads/writes.
        }
        if(FD_ISSET(Szocket, &my_fds))
        {
            // Szocket is ready...
        }
    }
    @@4: They were not -- the lines were commented out.

    @@2:
    You're still not capturing send/recv's return value. When you do:
    Code:
    recv(kSock, buf, sizeof(buf), 0);
    After that call, how much data is in buf? You have no idea, and so you next call to send() is invalid. You must:
    Code:
    int ret;
    ret = recv(kSock, buf, sizeof(buf), 0);
    // check if ret is < 0 --- errors
    // check if ret is 0 --- closed socket
    // if ret > 0, then it's how many bytes are in buf.
    // Same with send():
    int send_ret;
    send_ret = send(kSock, buf, ret, 0);
    // if send_ret is < 0 -- errors
    // if send_ret is 0 -- closed socket
    // if send_ret is > 0, that's how many bytes where sent
    // DO NOT ASSUME that ret == send_ret  if send_ret > 0.
    You might recv() 200 bytes, but only be able to send() 100 of those. You will have to buffer them somewhere.
    Additionally, you'll need to check, if you're using non-blocking sockets, for the would-block condition. (errno == EWOULDBLOCK or or WSAGetLastError() == WSAEWOULDBLOCK) if send() or recv() return less than 0. Read the manual pages.

    You should fill out your fd_set each time, and your time structure too -- select() may change them.
    Last edited by Cactus_Hugger; 07-18-2009 at 03:02 PM.
    long time; /* know C? */
    Unprecedented performance: Nothing ever ran this slow before.
    Any sufficiently advanced bug is indistinguishable from a feature.
    Real Programmers confuse Halloween and Christmas, because dec 25 == oct 31.
    The best way to accelerate an IBM is at 9.8 m/s/s.
    recursion (re - cur' - zhun) n. 1. (see recursion)

  6. #6
    Registered User
    Join Date
    Mar 2009
    Posts
    76
    This should be right, right?

    Code:

    Code:
    #include <windows.h> //Required for socket init
    #include <iostream>
    #include <sys/time.h>
    using namespace std;
    int main(){
        
     int psize = 1500;
        
        char buf[psize];
        char uua[psize];
    WSAData wsdata; //Declare WSAData
    WORD wsver=MAKEWORD(2, 0); //We want Winsock 2.0
    WSAStartup(wsver, &wsdata);
    //WSA starting code
     
     
    //Hosting thing.
    
    SOCKET Szocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);  
     SOCKADDR_IN serverInf;
     serverInf.sin_family=AF_INET;
     serverInf.sin_addr.s_addr=INADDR_ANY;
     serverInf.sin_port=htons(15776);   
        bind(Szocket,(SOCKADDR*)(&serverInf),sizeof(serverInf));
     listen(Szocket,1);   
     SOCKET TempSock=SOCKET_ERROR;
     while(TempSock==SOCKET_ERROR)
     {
      std::cout<<"Waiting for incoming connections...\r\n";
      TempSock=accept(Szocket,NULL,NULL);
     }
     u_long iMode=1;
     //ioctlsocket(Szocket,FIONBIO,&iMode);
     Szocket=TempSock;
     std::cout<<"Client connected!\r\n\r\n"; 
     
     
     
     
     
     
     
     
    SOCKET kSock=socket(AF_INET, SOCK_STREAM, 0);
    sockaddr_in sin;
    sin.sin_port=htons(15777); //Connect to port 15777
    sin.sin_addr.s_addr=inet_addr("127.0.0.1"); //Connect to localhost
    sin.sin_family=AF_INET;
    //ioctlsocket(Szocket,FIONBIO,&iMode);
    if(connect(kSock,(sockaddr*)&sin, sizeof(sin)) == SOCKET_ERROR){ //Check the condition
    std::cout<<"Connect failed, error: "<<WSAGetLastError(); //Returns error code
    WSACleanup(); //Cleanup the library
    std::string lisquit;
    std::cin>>lisquit;
    }
    std::cout<<"Connection successful!\n";
     
    timeval tiz;
    tiz.tv_sec = 1;
    tiz.tv_usec = 0;
    FD_SET OrigMC;
    FD_SET PrxMC;
     
     
     
    
    while (true)
    {
    cout<<"Loop started.\n";
    fd_set my_fds;
    FD_ZERO(&my_fds);
    FD_SET(kSock, &my_fds);
    FD_SET(Szocket, &my_fds);
    int select_ret;
    select_ret = select((kSock > Szocket ? kSock : Szocket) + 1, &my_fds, &my_fds, NULL, NULL);
    if(select_ret > 0)
    {
    
        if(FD_ISSET(Szocket, &my_fds))
        {
    int seret;                 
    seret = recv(Szocket, buf, sizeof(buf), 0);  
    send(kSock,buf,seret,0);
    cout<<"From pxy to MC: "<<buf<<"\n\n";
        }
        if(FD_ISSET(kSock, &my_fds))
        {
    int ret;                 
    ret = recv(kSock, uua, sizeof(uua), 0);  
    send(Szocket,uua,ret,0);
    cout<<"From MC to pxy: "<<uua<<"\n\n";
        }
    }
     
    Sleep(50);
    //      Azjherben.org
    }
     
     
    }

    Anything else?
    Last edited by azjherben; 07-18-2009 at 05:58 PM.

  7. #7
    Registered User
    Join Date
    Mar 2009
    Posts
    76
    Also, could this send binary data?
    If not, what do I have to do to allow it to?

  8. #8
    int x = *((int *) NULL); Cactus_Hugger's Avatar
    Join Date
    Jul 2003
    Location
    Banks of the River Styx
    Posts
    902
    Well... mixed. In some ways, it's a regression:
    1) Indent your code.
    To elaborate, indent the code, not the version you're posting to boards. It aids readability, maintainability, and a few more -abilities that I'm not going to enumerate.

    Yes, it will work with binary data. send() and recv() work with byte arrays -- similar to memcpy(), for example. People often screw up serialization (or just don't do it at all), however, this is outside the scope of sockets, as the same rules apply to things like files. If you're just writing a 'proxy', then you probably don't have to worry about this -- you're just taking one byte stream and moving it to another socket.

    One thing I did not think of in my earlier post: If you can pass the same fd_set multiple times to select(). MSDN says nothing on this point, whereas the linux man page says:
    Three independent sets of file descriptors are watched.
    ...which seems to indicate that they should be in different sets, although I am not sure.

    You get the return values, but you don't check them. You must handle the <= 0 cases. Also, we still don't capture the return value from send().

    I think you're not aware of a few things:
    1) recv() might not fill the buffer passed to it.
    2) send() might not send the entire buffer passed to it.

    If you're using only a single socket, and it's blocking, this isn't that big of a deal -- we just re-call recv() if we need more data, or we re-call send() until the transfer is complete.

    It gets more complicated with multiple sockets however. You're going to have to buffer the data, as your call to send() might not be able to handle all the data. (If one is slower than the other, which IS going to be the case.) Alternatively, I suppose you could switch to blocking for a second, send the data (you still need to check those return codes, #2 still applies), and then switch back...

    Finally, you should clean up some of your existing error handling. For example, there are code paths where you call WSACleanup(), but proceed to the body of the program anyways. You've also got a variable -- lisquit? -- that you never use. If you're in Windows, Ctrl+F5 will run & pause. Generally using stdin to pause before termination is a poor choice.
    Last edited by Cactus_Hugger; 07-18-2009 at 09:04 PM.
    long time; /* know C? */
    Unprecedented performance: Nothing ever ran this slow before.
    Any sufficiently advanced bug is indistinguishable from a feature.
    Real Programmers confuse Halloween and Christmas, because dec 25 == oct 31.
    The best way to accelerate an IBM is at 9.8 m/s/s.
    recursion (re - cur' - zhun) n. 1. (see recursion)

  9. #9
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    ...which seems to indicate that they should be in different sets, although I am not sure.
    They must be different file sets. The select() function will modify the 3 file descriptor sets as it processes them. Depending on the order it does this, you will end up not checking if a file descriptor can be read from or written to because that bit has already been cleared by earlier processing.

    Not to mention that if the 3 descriptor sets are shared, the results become worthless. If your fdset has a bit set, does that mean it can be read from or written to? You don't know, because you used the same set for both.

  10. #10
    int x = *((int *) NULL); Cactus_Hugger's Avatar
    Join Date
    Jul 2003
    Location
    Banks of the River Styx
    Posts
    902
    Not to mention that if the 3 descriptor sets are shared, the results become worthless. If your fdset has a bit set, does that mean it can be read from or written to? You don't know, because you used the same set for both.
    You could always just call both recv() and send() on the socket. :-)

    That makes sense though -- not exactly sure what I was thinking earlier. Perhaps I've been epoll()ing too long.
    long time; /* know C? */
    Unprecedented performance: Nothing ever ran this slow before.
    Any sufficiently advanced bug is indistinguishable from a feature.
    Real Programmers confuse Halloween and Christmas, because dec 25 == oct 31.
    The best way to accelerate an IBM is at 9.8 m/s/s.
    recursion (re - cur' - zhun) n. 1. (see recursion)

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Simple C++ code doesn't work
    By alex_dude_122 in forum C++ Programming
    Replies: 6
    Last Post: 10-18-2006, 12:53 PM
  2. i cant get my code to work! (hawknl)
    By Guido in forum Networking/Device Communication
    Replies: 3
    Last Post: 05-23-2004, 01:20 AM
  3. cant get code to work
    By duffy in forum C Programming
    Replies: 13
    Last Post: 10-20-2002, 05:23 AM
  4. << !! Posting Code? Read this First !! >>
    By kermi3 in forum Linux Programming
    Replies: 0
    Last Post: 10-14-2002, 01:30 PM