Question

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>

int main()
{

int sock;
    struct sockaddr sock_name = {AF_UNIX, "Fred"};
    socklen_t len=sizeof(struct sockaddr)+5;


    if( (sock=socket(AF_UNIX,SOCK_STREAM,0)) ==-1)
    {
        printf("error creating socket");
        return -1;
    }

    if( bind(sock,&sock_name,len) != 0 )
    {

        printf("socket bind error");
        return -1;
    }

    close(sock);


return 0;
}

After the first run, this program keeps reporting binding error. I tried to change the name of the sockaddr. It works again. But after changing it back to "Fred" (in this case), the error continues. Is something being stored in memory I didn't clear? Why does this happen and how could I fix it?

I guess I have found the problem. After the first run, I find a file named "Fred" in the current directory. I removed the file and my program worked again. Why does bind method generate a file in the current directory?

Was it helpful?

Solution

When used with Unix domain sockets, bind(2) will create a special file at the specified path. This file identifies the socket in much the same way a host and port identify a TCP or UDP socket. Just like you can't call bind twice to associate two different sockets with a given host and port*, you can't associate more than one Unix socket

But why doesn't the file disappear when you call close(2)? After all, closing a TCP socket makes the host and port it was bound to available for other sockets.**

That's a good question, and the short answer is, it just doesn't.

So it's customary (at least in example code) to call unlink(2) prior to binding. The Unix domain socket section of Beej's IPC guide has a nice example of this.

*With versions of the Linux kernel >= 3.9, this isn't exactly true.

**After TIME_WAIT or immediately if you use the SO_REUSEADDR socket option.

EDIT

You said this is your teacher's code, but I suggest that you replace your printf calls with perror:

if( bind(sock,&sock_name,len) != 0 )
{

    perror("socket bind error");
    return -1;
}

...which will print out a human-readable representation of the real problem encountered by bind(2):

$ ./your-example-executable
$ ./your-example-executable 
socket bind error: Address already in use

Programming doesn't have to be so inscrutable!

OTHER TIPS

When you successfully open a socket, it stays open until it is closed (even if your program terminates).

It appears that the question code is not closing the socket in the event of an (such as the failure of bind()).

Two processes cannot generally open the same socket.

Each time the code is executed, it is a new process, attempting to open the same socket.

The code needs a better scheme to handle errors.

This is how I would do it:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>

#define MY_FALSE (0)
#define MY_TRUE  (-1)

int main()
   {
   int rCode=0;
   int sock = (-1);
   char *socketFile = "Fred");
   struct sockaddr sock_name = {AF_UNIX, socketFile};
   socklen_t len=sizeof(struct sockaddr)+5;
   int bound = MY_FALSE;

   if((sock=socket(AF_UNIX,SOCK_STREAM,0)) ==-1)
      {
      printf("error creating socket");
      rCode=(-1);
      goto CLEANUP;
      }

   if( bind(sock,&sock_name,len) != 0 )
      {
      printf("socket bind error");
      rCode=(-1);
      goto CLEANUP;
      }
   bound=MY_TRUE;

This single 'cleanup' area can be used to free allocated memory, close sockets & files, etc.

CLEANUP:

   if((-1) != sock)
       close(sock);

   if(bound)
       unlink(socketFile);

   return 0;
   }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top