Thread: Non-blocking socket connection problem

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    VIM addict
    Join Date
    May 2009
    Location
    Chennai, India
    Posts
    43

    Arrow Non-blocking socket connection problem

    Hi all,

    This is my first post in this forum.

    I have a issue with socket connection related to non-blocking sockets. Here is the code which i am using under Linux

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <fcntl.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <sys/ioctl.h>
    
    #define PORT 0x1234
    
    #define PASS	0
    #define FAIL	1
    
    int main()
    {
    	int listenfd,sendfd,acceptfd;
    	struct sockaddr_in serveraddr,clientaddr;
    	int retc;
    	int accetfd;
    	int servlen = sizeof(serveraddr);
    	char *recv_buffer, *send_buffer;
    	int i,j,k;
    	int err_cnt = 0;
    	int flag;
        	int send_done;
        	int bytes_to_send, bytes_to_read;
        	int num_bytes_send, num_bytes_read;
    
    	/* initialise all */
    	listenfd = sendfd = acceptfd = 0;
    	recv_buffer = send_buffer = NULL;
    
    	/* allocate buffer for both send and receive */
    	recv_buffer = (char *)malloc (1024 * 1024);
    	if(recv_buffer == NULL)
    	{
    		printf("Can't allocate memory\n");
    		retc = FAIL;
    		goto done;
    	}
    	send_buffer = (char *)calloc(1, 1024 * 1024);
    	if(send_buffer == NULL)
    	{
    		printf("Can't allocate memory for send buffer\n");
    		retc = FAIL;
    		goto done;
    	}
    
    	/* open socket for send and receive */
    	listenfd = socket(AF_INET, SOCK_STREAM, 0);
    	if(listenfd < 0)
    	{
    		perror("listenfd socket failed");
    		retc = FAIL;
    		goto done;
    	}
    	sendfd = socket(AF_INET, SOCK_STREAM, 0);
    	if(sendfd < 0)
    	{
    		perror("sendfd socket failed");
    		retc = FAIL;
    		goto done;
    	}
    	
    	/* make both send and receive non-blocking */
    	if ( (flag = fcntl(listenfd, F_GETFL, NULL)) < 0)
    	{
            	perror("listenfd fcntl:");
            	retc = FAIL;
            	goto done;
        	}
    
        	flag |= O_NONBLOCK;
    
        	if ( fcntl(listenfd, F_SETFL, flag) < 0)
    	{
            	perror("listenfd fcntl:");
            	retc = FAIL;
            	goto done;
        	}
        	if ( (flag = fcntl(sendfd, F_GETFL, NULL)) < 0)
    	{
        	    perror("sendfd fcntl:");
        	    perror("listenfd fcntl:");
        	    retc = FAIL;
        	}
    
        	flag |= O_NONBLOCK;
    
        	if ( fcntl(sendfd, F_SETFL, flag) < 0)
    	{
        	    perror("sendfd fcntl:");
        	    perror("listenfd fcntl:");
        	    retc = FAIL;
        	}
    
    	/* Bind to socket */
    	serveraddr.sin_family = AF_INET;
    	serveraddr.sin_addr.s_addr = INADDR_ANY;
    	serveraddr.sin_port = htons(PORT);
    
    	clientaddr.sin_family = AF_INET;
    	clientaddr.sin_addr.s_addr = INADDR_ANY;
    	clientaddr.sin_port = htons(PORT);
    
    	if (bind (listenfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) == -1)
    	{
    		perror("Bind error under listenfd");
    		retc = FAIL;
    		goto done;
    	}
    	
    	/* listen for incoming connection */
    	if (listen(listenfd, 1) == -1)
    	{
    		perror("Listen socket error");
    		retc = FAIL;
    		goto done;
    	}
    
    	/* establisg connection */
    	if (connect(sendfd, (struct sockaddr *)&clientaddr,sizeof(struct sockaddr)) < 0)
    	{
    		perror("Connect call failed");
    		retc = FAIL;
    		goto done;
    	}
    	
    	/* accept incoming connection */
    	if (accept(listenfd, (struct sockaddr *)&serveraddr, &servlen) < 0)
    	{
    		perror("Accept call failed");
    		retc = FAIL;
    		goto done;
    	}
    
    	retc = PASS;	
    	
    	/* send and receive data */
    	for ( k = 0; k < 100; k++)
    	{
            	bytes_to_send = 1024 * 16;
            	i = 0;
            	j = 0;
            	bytes_to_read = 1024 * 16;
            	send_done = 0;
            	while(1)
    		{
           			if ( send_done == 0)
    			{
           				num_bytes_send = send(sendfd, &send_buffer[j], bytes_to_send,0);
           			        if (num_bytes_send == -1)
    				{
           			             perror("Sending data failed");
           			             retc = FAIL;
           			             break;
           			        }
    				else if (num_bytes_send == 0)
    				{
           			             send_done = 1;
           			        }
    				else
    				{
           			             bytes_to_send -= num_bytes_send;
           			             j += num_bytes_send;
           			        }
           			}
           			if (retc == FAIL)
           				break;
           			num_bytes_read = read(acceptfd, &recv_buffer[i], bytes_to_read);
                		if (num_bytes_read == -1)
                		{
                			perror("Receive data failed");
                			retc = FAIL;
                			break;
                		}
                		else if (num_bytes_read == 0)
    			{
                			break; /* Break on EOF */
                		}
                		else 
    			{
                			bytes_to_read -= num_bytes_read;
                			i += num_bytes_read;
                		}
            	}
            	if ( retc == FAIL)
            		break;
            	for ( i = 0; i < 1024 * 16; i++)
    		{
            		if ( recv_buffer[i] != (char)i)
    			{
            			printf("Error: receive data not correct, \n");
            		        printf("expected : 0x%x, received: 0x%x\n", i, recv_buffer[i]);
            		        retc = FAIL;
            		        err_cnt ++;
            		        if ( err_cnt > 10) break;
            		}
            	}
            	if (retc != PASS)
            		break;
        	}
    done:
        	if ( sendfd != 0 )
    	{
        		if (close(sendfd ) < 0)
    			perror( "close sendfd:");
        	}
        	if ( acceptfd != 0 )
    	{
        		if (close(acceptfd ) < 0)
    		perror( "close accetfd:");
        	}
    	if ( listenfd != 0)
    	{
    		if (close(listenfd) < 0)
    			perror("close listen:");
    	}
    	if ( send_buffer != NULL)
            	free(send_buffer);
        	if ( recv_buffer != NULL)
            	free(recv_buffer);
    
    	printf("Test.......");
    	if(retc == PASS)
    		printf("PASSED\n");
    	else
    		printf("FAILED\n");
    
    	return retc;
    }

    When i try to run this code i am getting error while connecting to socket

    Connect call failed: Operation now in progress

    Can anyone help..... Thanks in advance

    -BalaC-

  2. #2
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    What are you trying to do here:

    Quote Originally Posted by cbalu View Post
    /* Bind to socket */
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_addr.s_addr = INADDR_ANY;
    serveraddr.sin_port = htons(PORT);

    clientaddr.sin_family = AF_INET;
    clientaddr.sin_addr.s_addr = INADDR_ANY;
    clientaddr.sin_port = htons(PORT);
    I do not see a purpose to setting these sockets non block; that will only complicate your efforts in what I presume is your first attempt at tcp/ip networking.
    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

  3. #3
    VIM addict
    Join Date
    May 2009
    Location
    Chennai, India
    Posts
    43
    Hi MK27,

    Thanks for your reply, i am new to sockets in C language i thought of merging both server and client code in single .c file to just test whether i was able to send and receive data over the socket i followed so many tutorial over the internet and came up with this piece of code.

    So started with non-blocking approach and ended up in error.

    Can you provide me a detailed explanation what i am doing wrong in the code...Thanks in advance for your time

  4. #4
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by cbalu View Post
    Can you provide me a detailed explanation what i am doing wrong in the code...Thanks in advance for your time
    Your code actually looks pretty good* -- but I myself would never write that much all at once without, obviously, knowing if any of it will work, because when you are finished and it doesn't work, you now have quite a haystack to dissect! You should have started with the most simple conceivable task, which in this case would be to just write a client and try and connect that to a server somewhere on the internet, the same way your browser does. THEN start thinking about the server, etc. There is a real possibility that what you want to do here will not work no matter what, depending on your actual internet connection (unless you use 127.0.0.1 or two computers on one router -- a LAN).

    Since you are apparently working in a *nix environment, one thing you might want to look into is unix local sockets, which are almost identical to (but slightly simpler than) tcp/ip inet sockets. That will allow you to do client-server stuff without using the net at all.

    Anyway, the problem I highlighted in my last post is that you use a macro INADDR_ANY, which is equal to 0. That is not a valid address. My memory of these things is slightly fogging, but I would guess you believe this field is going to be filled in by a socket function, or you have confused the sin_addr.s_addr with a little chunk at the end of a sockaddr_in struct called sin_zero, which does need to
    be zero'd, eg:
    Code:
    memset(&(connto.sin_zero),0,8);
    So, you need a real address to assign to both the client and server sin_addr.s_addr. I have never tried using an identical address for both of them, so I don't know if that will work, ie. I do not know if you will be able to connect to yourself using inet sockets.


    * I'm not promising you anything tho
    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

  5. #5
    VIM addict
    Join Date
    May 2009
    Location
    Chennai, India
    Posts
    43
    Just one theoritical query,

    Consider one simple server-client application where both running under the same system with only one eth interface then obviously address & port number for server and client must be same in order to communicate each other. If this scenario works then i think the code i have posted will also work

    And off course i will try your suggestion...And get back to you

  6. #6
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by cbalu View Post
    Just one theoritical query,
    Yep, that's theoretical. I dunno if it will work, but you can try.
    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

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,666
    IMO, it would be a lot easier to look at (and comment on), if you split the code into functions, and not one bloated main() with several hundred lines of code (and complex logic and indentation to match).
    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.

  8. #8
    VIM addict
    Join Date
    May 2009
    Location
    Chennai, India
    Posts
    43
    I have splitted up my code and now i have only socket connection logic in my code. Here is the code now i am currently working with

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <fcntl.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <sys/ioctl.h>
    
    #define PORT 0x1234
    #define SERVER_ADDR "127.0.0.1"
    #define CLIENT_ADDR "127.0.0.1"
    #define PASS	0
    #define FAIL	1
    
    int main()
    {
    		int listenfd,sendfd,acceptfd;
    		struct sockaddr_in serveraddr,clientaddr;
    		int retc;
    		int accetfd;
    		int servlen = sizeof(serveraddr);
    		char *recv_buffer, *send_buffer;
    		int flag;
    
    		/* initialise all */
    		listenfd = sendfd = acceptfd = 0;
    		recv_buffer = send_buffer = NULL;
    
    		/* allocate buffer for both send and receive */
    		recv_buffer = (char *)malloc (1024 * 1024);
    		if(recv_buffer == NULL)
    		{
    				printf("Can't allocate memory\n");
    				retc = FAIL;
    				goto done;
    		}
    		send_buffer = (char *)calloc(1, 1024 * 1024);
    		if(send_buffer == NULL)
    		{
    				printf("Can't allocate memory for send buffer\n");
    				retc = FAIL;
    				goto done;
    		}
    
    		/* open socket for send and receive */
    		listenfd = socket(AF_INET, SOCK_STREAM, 0);
    		if(listenfd < 0)
    		{
    				perror("listenfd socket failed");
    				retc = FAIL;
    				goto done;
    		}
    		sendfd = socket(AF_INET, SOCK_STREAM, 0);
    		if(sendfd < 0)
    		{
    				perror("sendfd socket failed");
    				retc = FAIL;
    				goto done;
    		}
    
    		/* make both send and receive non-blocking */
    #if 1
    		if ( (flag = fcntl(listenfd, F_GETFL, NULL)) < 0)
    		{
    				perror("listenfd fcntl:");
    				retc = FAIL;
    				goto done;
    		}
    
    		flag |= O_NONBLOCK;
    
    		if ( fcntl(listenfd, F_SETFL, flag) < 0)
    		{
    				perror("listenfd fcntl:");
    				retc = FAIL;
    				goto done;
    		}
    		if ( (flag = fcntl(sendfd, F_GETFL, NULL)) < 0)
    		{
    				perror("sendfd fcntl:");
    				perror("listenfd fcntl:");
    				retc = FAIL;
    		}
    
    		flag |= O_NONBLOCK;
    
    		if ( fcntl(sendfd, F_SETFL, flag) < 0)
    		{
    				perror("sendfd fcntl:");
    				perror("listenfd fcntl:");
    				retc = FAIL;
    		}
    #endif
    
    		/* Get system ip */
    		if ( ( inet_aton(SERVER_ADDR, &serveraddr.sin_addr.s_addr) == 0 ) || ( inet_aton(CLIENT_ADDR, &clientaddr.sin_addr.s_addr) == 0 ) )
        	{
            	perror("Can't assign server/client address");
            	retc = FAIL;
    			goto done;
        	}
    
    		/* Bind to socket */
    		serveraddr.sin_family = AF_INET;
    		//serveraddr.sin_addr.s_addr = INADDR_ANY;
    		serveraddr.sin_port = htons(PORT);
    		memset(&serveraddr.sin_zero,0,8);
    
    		clientaddr.sin_family = AF_INET;
    		//clientaddr.sin_addr.s_addr = INADDR_ANY;
    		clientaddr.sin_port = htons(PORT);
    		memset(&clientaddr.sin_zero,0,8);
    
    		printf("My system ip address is %ld\n", serveraddr.sin_addr.s_addr);
    		if (bind (listenfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) == -1)
    		{
    				perror("Bind error under listenfd");
    				retc = FAIL;
    				goto done;
    		}
    
    		/* listen for incoming connection */
    		if (listen(listenfd, 1) == -1)
    		{
    				perror("Listen socket error");
    				retc = FAIL;
    				goto done;
    		}
    
    		/* establisg connection */
    		if (connect(sendfd, (struct sockaddr *)&clientaddr,sizeof(struct sockaddr)) < 0)
    		{
    				perror("Connect call failed");
    				retc = FAIL;
    				goto done;
    		}
    
    		/* accept incoming connection */
    		if (accept(listenfd, (struct sockaddr *)&serveraddr, &servlen) < 0)
    		{
    				perror("Accept call failed");
    				retc = FAIL;
    				goto done;
    		}
    
    		retc = PASS;	
    
    done:
    		if ( sendfd != 0 )
    		{
    				if (close(sendfd ) < 0)
    						perror( "close sendfd:");
    		}
    		if ( acceptfd != 0 )
    		{
    				if (close(acceptfd ) < 0)
    						perror( "close accetfd:");
    		}
    		if ( listenfd != 0)
    		{
    				if (close(listenfd) < 0)
    						perror("close listen:");
    		}
    		if ( send_buffer != NULL)
    				free(send_buffer);
    		if ( recv_buffer != NULL)
    				free(recv_buffer);
    
    		printf("Test.......");
    		if(retc == PASS)
    				printf("PASSED\n");
    		else
    				printf("FAILED\n");
    
    		return retc;
    }
    In this code if i disable non-blocking call then my code works fine. But if i enable non-blocking call then i am getting the following error

    Connect call failed: Operation now in progress

  9. #9
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Wow, cbalu, I just remembered what INADDR_ANY is for; it does gets filled in! None of the stuff I have on file has it in because I always provide an address, but I do remember using that at some point.

    I am very sorry about that -- you must have known this, why didn't you say anything?

    Anyway, it is good your code is working, sans non-block. I do not understand the nature of the error, but I still believe there is no purpose to the non-block, since this is a one to one client-server relationship.
    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

  10. #10
    VIM addict
    Join Date
    May 2009
    Location
    Chennai, India
    Posts
    43
    Hi MK27, today only i came to know the functionality of INADDR_ANY. If i would have known it then i would certainly post it (as i don't want to waste others time).

    Now upto accept call my code works fine under blocking sockets then if i try to send data using the write call i am getting error, which states that i am using Bad address

    And one more thing is that one of my colleague suggested me that i have done coding wrongly. I need to run server and client as separate program or else i need to make them run in separate threads to make it communicate each other. Is it true?

  11. #11
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by cbalu View Post
    And one more thing is that one of my colleague suggested me that i have done coding wrongly. I need to run server and client as separate program or else i need to make them run in separate threads to make it communicate each other. Is it true?
    Yep. Your program will stop at listen(), and of course never receive anything. I don't know why I didn't notice that -- probably I stopped at the first problem I thought I found...embarrassing. Sorry again. It is good for me to refresh my memory about these things

    You don't have to thread -- you can use fork(). Probably you will then want to write a single function which sets up a socket, given an appropriate set of parameters, and you can call that from the parent/server and child/client.

    I still think you should write a simple client that can communicate with a real server somewhere -- if you can make that happen, you know everything is working.

    You can use gethostbyname(), in netdb.h, to translate (eg) "www.cprogramming.com" into a host address you use with connect() then you send() a GET request using a path, so if you wanted a page like "www.cprogramming.com/someplace/sompage.html"

    Code:
    char request[]="GET /someplace/sompage.html HTTP/1.0\r\n\r\n";
    Then you should be able to recv() an answer.

    Once that works you will have a better feel for how the flow of execution works. If it is easier to write two separate programs rather than using fork(), just do that. IMO you might as well, there is no reason to put all this in one piece of source code.

    If you want some examples, I have a bunch of client and server things I wrote months ago, some of which I use to do file transfer and issue remote commands on a LAN. Just ask.
    Last edited by MK27; 05-26-2009 at 11:36 AM.
    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

  12. #12
    VIM addict
    Join Date
    May 2009
    Location
    Chennai, India
    Posts
    43
    Sorry MK27, actually i have iptables enabled which prevented this behavior. It is working fine with hard coded IP.

  13. #13
    VIM addict
    Join Date
    May 2009
    Location
    Chennai, India
    Posts
    43
    Ya i can able to send and receive contents without using fork() call. The code which i have attached has the complete logic which i have been using.

    So you mean to say that without fork() call my code is expected to fail?

  14. #14
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by cbalu View Post
    Ya i can able to send and receive contents without using fork() call. The code which i have attached has the complete logic which i have been using.

    So you mean to say that without fork() call my code is expected to fail?
    That's pretty interesting, maybe because of the NON_BLOCK. The client and server are all part of a single process? Post the code you have right now, I'm interested in trying it...ah, I see you do have inet_aton in there.

    I just wanted to indicate to you that that is *not* the normal way to go. But if you think it is a good idea, then by all means forge ahead. And do post the code.
    Last edited by MK27; 05-27-2009 at 08:59 AM.
    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

  15. #15
    VIM addict
    Join Date
    May 2009
    Location
    Chennai, India
    Posts
    43
    Here is the final code which i have with sockets as blocking and logic of getting the system IP dynamically without system() call and send & receive on sockets

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Problem with simple socket client/server program
    By spencer88 in forum C Programming
    Replies: 6
    Last Post: 05-05-2009, 11:05 PM
  2. Socket Connection Still Alive!!
    By maven in forum Networking/Device Communication
    Replies: 2
    Last Post: 07-21-2006, 02:14 PM
  3. socket problem
    By RevengerPT in forum C Programming
    Replies: 9
    Last Post: 01-17-2006, 09:07 AM
  4. Weird connection problem.
    By tilex in forum Networking/Device Communication
    Replies: 6
    Last Post: 02-06-2005, 10:11 AM
  5. problem closing socket
    By Wisefool in forum Networking/Device Communication
    Replies: 2
    Last Post: 10-29-2003, 12:19 PM

Tags for this Thread