Thread: Listen() Not Blocking Correctly

  1. #1
    Registered User
    Join Date
    May 2008
    Location
    Australia
    Posts
    230

    Listen() Not Blocking Correctly

    So uhh... Whenever I run this network program listen isn't blocking properly. It's not waiting for incoming connections, it's just instantly going down to accept(), and accept() is returning an error... I have no idea why listen() isn't blocking. I ran this program by itself (with no interacting client program running) and that is what it does. Output:

    Listening on socket...
    ERROR.

    If I replace printf("ERROR."); with perror("ERROR."); it says:

    Listening on socket...
    ERROR. No error found

    But that doesn't really make sense because it wouldn't be going through the if statement if there was no error, it will only go through the if statement if the accept call returns INVALID_SOCKET. Ok here is the code:

    Code:
    #include <iostream>
    #include <winsock2.h>
    #include <ws2tcpip.h>
    #include <cstring>
    #include <Mstcpip.h>
    
    #define MYPORT "3490"
    #define BACKLOG 10
    
    using std::cout;
    using std::cin;
    using std::endl;
    
    WSADATA wsaData;
    
    int main(int argc, char * argv[]) {
    	int wsaReturnVal = WSAStartup(MAKEWORD(1, 1), &wsaData);
    	if (wsaReturnVal) {
    		cout << "Error number: " << wsaReturnVal << endl;
    		exit(1);
    	}
    
    	struct addrinfo hints, *res = NULL;
    	struct sockaddr_storage *their_addr;
    	SOCKET sockfd, newfd = NULL;
    
    	memset(&hints, 0, sizeof(hints));
    
    	hints.ai_family = AF_INET;
    	hints.ai_flags = AI_PASSIVE;
    	hints.ai_socktype	= SOCK_STREAM;
    
    	getaddrinfo(NULL, MYPORT, &hints, &res);
    
    	sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
    	if (bind(sockfd, res->ai_addr, res->ai_addrlen) == -1) {
    		printf("Socket bind error.");
    		exit(1);
    	}
    
    	if (listen(sockfd, BACKLOG) == -1) {
    		printf("Socket listen error.");
    		exit(1);
    	}
    
    	printf("Listening on socket...\n");
    	closesocket(sockfd);
    	int addr_size = sizeof(their_addr);
    
    	if ((newfd = accept(newfd, (struct sockaddr *)&their_addr, &addr_size)) == INVALID_SOCKET) {
    		printf("ERROR.");
    		closesocket(newfd);
    		exit(1);
    	}
    
    	char buffer[255];
    	recv(newfd, buffer, 255, 0);
    	send(newfd, buffer, 255, 0);
    
    
    	freeaddrinfo(res);
    
    	if (WSACleanup()) {
    		cout << "Cleanup Error." << endl;
    		exit(1);
    	}
    
    }
    Thanks!
    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    MS winsock uses a different function to return the last socket error.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    May 2008
    Location
    Australia
    Posts
    230
    As in other than perror? Even if that's the case the problem still stands Unless you mean something else that I don't understand.
    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.

  4. #4
    Registered User valaris's Avatar
    Join Date
    Jun 2008
    Location
    RING 0
    Posts
    507
    listen doesn't block. At least in Berkely sockets. Listen puts the socket into listening mode, usually with a backlog of clients to put in a queue until they can be accepted. It's accept that will accept the next client from this queue. I think your error comes from higher up then accept as well. Im pretty sure that bind takes a sockaddr struct, and at the very least it takes a struct that has been allocated some memory, right now you are passing an empty pointer.

    After checking documentation at http://www.sockets.com/winsock.htm#Bind this seems to be the case.
    Last edited by valaris; 10-26-2008 at 01:48 PM.

  5. #5
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by pobri19 View Post

    Code:
    	closesocket(sockfd);
    	int addr_size = sizeof(their_addr);
    
    	if ((newfd = accept(newfd, (struct sockaddr *)&their_addr, &addr_size)) == I
    Thanks!
    This is very incorrect. accept returns a new fd to a new anonymous socket for a connection, but this is in reply to a connect request on an existing, listening socket (which is the first argument to accept). The way you have it done here, the first argument should be sockfd, not newfd. But sockfd was just closed anyway!
    Why did you do that after you had it all set up?

    The only purpose of a socket set to listen is to accept new connections, which then get a socket of their own for the actual connection. But you do need an open listening socket for the accept.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  6. #6
    Hacker MeTh0Dz's Avatar
    Join Date
    Oct 2008
    Posts
    111
    Quote Originally Posted by Salem View Post
    MS winsock uses a different function to return the last socket error.
    Yes...

    WSAGetLastError()

  7. #7
    Registered User
    Join Date
    May 2008
    Location
    Australia
    Posts
    230
    Yeah MK27 that was a mistake that I didn't see. Anyways, bind is the thing that is failing according to the output.
    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.

  8. #8
    Registered User
    Join Date
    Oct 2008
    Posts
    2
    A other question. You can spesify the number of clients the listen will say have had got the connection. f.eks listen(fd, 5), 5 clients will be in the internal queue of the listener. But can 5 number change when the listen function has been used one time? What will happend with the clients in the listen queue then if the number gets smaler than the number already in the queue.

  9. #9
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by 256Doofus View Post
    A other question. You can spesify the number of clients the listen will say have had got the connection. f.eks listen(fd, 5), 5 clients will be in the internal queue of the listener. But can 5 number change when the listen function has been used one time? What will happend with the clients in the listen queue then if the number gets smaler than the number already in the queue.
    Forget the queue. It doesn't matter. It just tells the OS it's okay to send preemptive SYN packets to the clients waiting in the queue instead of waiting for an accept(). You are not going to lose client connections either way. Incoming connections won't get dropped, they'll just be a little delayed in the handshaking.

    And even if they did get dropped, TCP causes everybody to retry everything anyway. Bottom line, forget about the queue. Just set it to some reasonable value and move on.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  10. #10
    Registered User
    Join Date
    May 2008
    Location
    Australia
    Posts
    230
    It's all good now. Basically I just ditched those structures and the getaddrinfo for a struct sockaddr_in and assigned it manually. Works perfectly now. Cheers.
    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. non blocking operation
    By Alon in forum C++ Programming
    Replies: 4
    Last Post: 02-17-2009, 11:03 AM
  2. How to initialize a non blocking socket using only winsock library
    By *DEAD* in forum Networking/Device Communication
    Replies: 4
    Last Post: 01-18-2008, 07:03 AM
  3. What exactly does listen() do from winsock 1.1
    By *DEAD* in forum Networking/Device Communication
    Replies: 6
    Last Post: 12-14-2007, 06:48 PM
  4. the listen() function
    By Da-Nuka in forum Networking/Device Communication
    Replies: 9
    Last Post: 03-07-2005, 02:44 PM
  5. Non blocking listen() with winsock
    By manwhoonlyeats in forum C Programming
    Replies: 1
    Last Post: 12-08-2002, 07:00 PM