Flo
Flo

Reputation: 75

c++ socket accept blocks cout

I'm quite new to C++/C in general, so execuse me if this question might appear kinda stupid, but i'm really stuck here.

What I'm trying to do is a simple tcp server giving the user the opportunity to accept/decline incoming connections. I have a function named waitingForConnection() containing the main loop. It's called in the main function after the socket is sucessuflly bind and marked as passive.

What I'd expect is that, after the Client connects to the server, the function handleConnection() is getting called, causing the main loop to wait until the function is executed and only then to contiue. But what actually seems to happen is that the main loop continues to the next accept() call, which is blocking the thread, before handleConnection() is completley executed. The test-output "done" will only become visible if the client connects a second time and the thread wakes up again.

To me it seem like the code is executed completley out of order, which I believe is not possible, since the whole code should be executed in a single thread.

Console Output after first connection attempt ("n" is user input):

"Accept connection ? (y/n)"n

Console Output after second connection attempt:

"Accept connection ? (y/n)"n 
"doneAccept connection ? (y/n)"

Please note that I'm not looking for any workaround using select() or something similar, I'm just trying to understand why the code does what it does and maybe how to fix it by changing the structure.

int soc = socket(AF_INET, SOCK_STREAM, 0);

void handleConnection(int connectionSoc, sockaddr_in client){
   string choice;
   cout<<"Accept connection ? (y/n)";
   cin>>choice;
   if(choice=="y"||choice == "Y"){
     //do something here
   }else{
     close(connectionSoc);

   }
  cout<<"done";
}



void waitingForConnection(){

    while(running){

      sockaddr_in clientAddress;
      socklen_t length;
      length = sizeof(clientAddress);

      int soc1 = accept(soc,(struct sockaddr*)&clientAddress, &length);
      if(soc1<0){
          statusOutput("Connection failed");
      }else{
          handleConnection(soc1, clientAddress);
      }

   }

}

Upvotes: 1

Views: 901

Answers (1)

Slava
Slava

Reputation: 44258

Problem is that output to std::cout is buffered and you simply do not see that until it is flushed. As std::cin automatically flushes std::cout you get your output on the next input. Change your output to:

std::cout << "done" << std::endl;

and you would get expected behavior.

Upvotes: 4

Related Questions