为什么bind(套接字绑定)方法在当前目录中生成一个文件?

时间:2014-04-30 00:06:42

标签: c sockets process

#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;
}

首次运行后,该程序会报告绑定错误。我试图更改sockaddr的名称。它又有效了。但在将它改回&#34; Fred&#34; (在这种情况下),错误继续。存储在内存中的东西我不清楚吗?为什么会发生这种情况,我该如何解决?

我想我发现了这个问题。第一次运行后,我找到了一个名为&#34; Fred&#34;在当前目录中。我删除了文件,我的程序再次运行。为什么bind方法在当前目录中生成文件?

2 个答案:

答案 0 :(得分:1)

与Unix域套接字一起使用时,bind(2)将在指定路径创建一个特殊文件。此文件标识套接字的方式与主机和端口标识TCP或UDP套接字的方式非常相似。就像你不能两次调用bind来将两个不同的套接字与给定的主机和端口*相关联,你就无法关联多个Unix套接字

但是,当你拨打close(2)时,为什么文件不会消失?毕竟,关闭TCP套接字会使其绑定的主机和端口可用于其他套接字。**

这是一个很好的问题,简短的回答是,它只是没有。

因此,在绑定之前调用unlink(2)是习惯性的(至少在示例代码中)。 Beej's IPC guide的Unix域套接字部分有一个很好的example

*对于Linux内核的版本&gt; = 3.9,这不是exactly true

** TIME_WAIT之后或如果您使用SO_REUSEADDR套接字选项,则立即执行。

修改

您说这是您老师的代码,但我建议您使用printf替换perror来电:

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

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

...将打印出bind(2)所遇到的真正问题的人类可读表示:

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

编程并不是那么难以理解!

答案 1 :(得分:0)

成功打开套接字后,它会一直打开,直到它关闭(即使你的程序终止)。

似乎问题代码没有关闭套接字(例如bind()失败)。

两个进程通常不能打开同一个套接字。

每次执行代码时,都是一个新进程,试图打开同一个套接字。

代码需要一个更好的方案来处理错误。

我就是这样做的:

#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;

这个单一的清理工作&#39; area可以用来释放分配的内存,关闭套接字&amp;文件等。

CLEANUP:

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

   if(bound)
       unlink(socketFile);

   return 0;
   }