简体   繁体   English

套接字创建失败,但socket()和bind()方法不返回-1

[英]Socket creation fails but socket() and bind() method do not return -1

I working on network security based ios app. 我在基于网络安全的ios应用程序上工作。 I am trying to create a local socket for communication between threads. 我正在尝试创建一个本地套接字用于线程之间的通信。 I am doing this with the use of C language in ios app. 我在ios app中使用C语言这样做。

The problem is when I am creating and binding socket it does not gives any error. 问题是当我创建和绑定套接字时,它不会给出任何错误。 But when I try to send some data over this socket it fails. 但是,当我尝试通过此套接字发送一些数据时,它失败了。 Code for create and bind of socket is as follows: socket的create和bind代码如下:

int open_and_bind_socket(int *sockfd, const char *sname)
{
  //sname is socket name with full path
    size_t len = strlen (sname);

    size_t bytes = sizeof (struct sockaddr_un) + len + 1 - sizeof (((struct sockaddr_un *)0)->sun_path);

    struct sockaddr_un *unaddr = (struct sockaddr_un *)malloc (bytes);

     size_t size;

    if((*sockfd = socket (AF_LOCAL, SOCK_DGRAM, 0)) < 0)
    {
        AGENT_DEBUG(LOG_ERR, "%s", "Failed to open socket");
        return ~0;
    }

    unaddr->sun_family = AF_UNIX;
    unaddr->sun_len = bytes;
    memcpy(unaddr->sun_path, sname,len+1);

    size = (offsetof (struct sockaddr_un, sun_path)
                + strlen (unaddr->sun_path));

    if( bind(*sockfd,(struct sockaddr*)unaddr,size ) < 0)
    {
        AGENT_DEBUG(LOG_ERR, "%s", "Failed to bind the socket");
        AGENT_DEBUG(LOG_ERR, "Recvfrom MSG_PEEK Failure: %s, Socket Fd = %d\n",
                    strerror(errno), sockfd);
        return ~0;
    }

    if(0 != chmod(sname, 0666))
    {
        AGENT_DEBUG(LOG_ERR, "%s", "Unable to chmod Socket");
        return ~0;
    }
     //unlink(sname);
    return 0;
}

The code for sending data on socket is as follows: 在socket上发送数据的代码如下:

int data_send(int sockfd, tsIpcMsg *pMsgData)
{
    memset(x,'\0', sizeof(x));
    strcpy(x, buffer);
    strcat(x,"/AGENTSOCKET");
    size_t len = strlen (x);

    size_t bytes = sizeof (struct sockaddr_un) + len + 1 - sizeof (((struct sockaddr_un *)0)->sun_path);

    struct sockaddr_un *saun = (struct sockaddr_un *)malloc (bytes);

    memset(saun, 0, sizeof(*saun));
    saun->sun_family = AF_UNIX;    
    saun->sun_len=bytes;
    memcpy(saun->sun_path, x,len+1);
    memset(x,'\0', sizeof(x));

    if(-1 == (sendto(sockfd,(void*)pMsgData, sizeof(tsIpcMsg)+pMsgData->dataLen , 0, (struct sockaddr *)saun, sizeof(*saun))))
   {
        AGENT_DEBUG(LOG_ERR, "%s", "Failed to send message from thread to main");
        return ~0;
    }
    return 0;
}

When I log the errno returned by sendto() function it gives value '2' which means "No such file or directory exists: A component in pathname does not exist or is a dangling symbolic link, or pathname is empty." 当我记录sendto()函数返回的errno时,它给出值'2',这意味着“不存在这样的文件或目录:路径名中的组件不存在或者是悬挂的符号链接,或者路径名是空的。”

So, I think the socket is not getting created properly that's why sendto() method fails, while the socket and bind method does not give any error. 所以,我认为socket没有正确创建,这就是sendto()方法失败的原因,而socket和bind方法没有给出任何错误。

I am running this app on ios simulator(iPhone 7 plus). 我在ios模拟器(iPhone 7 plus)上运行这个应用程序。 The path to the socket is as follows: "/Users/Admin/Library/Developer/CoreSimulator/Devices/FC85979F-A627-4361-B4BD-DD794AB009C9/data/Containers/Data/Application/C45B9A05-F482-4011-8EA0-947A8C489367/Documents/app/AGENTSOCKET", where AGENTSOCKET is the name of the socket. 套接字的路径如下:“/ Users / Admin / Library / Developer / CoreSimulator / Devices / FC85979F-A627-4361-B4BD-DD794AB009C9 / data / Containers / Data / Application / C45B9A05-F482-4011-8EA0-947A8C489367 / Documents / app / AGENTSOCKET“,其中AGENTSOCKET是套接字的名称。

I am creating directory structure till app folder and then appending the socket name to it while creating socket in the following manner: 我正在创建目录结构直到app文件夹,然后在以下面的方式创建套接字时将套接字名称附加到它:

mkdir(path,0777);//path is till app directory
strcat(path, "/AGENTSOCKET");

Can anyone help me to fix this out. 任何人都可以帮我解决这个问题。

Thanks. 谢谢。

The sun_path field is limited to anywhere from 92-108 characters (depending on platform), including the null terminator. sun_path字段限制为92-108个字符(取决于平台),包括空终止符。 The x string you have shown for data_send() is 185 characters without a null terminator. 您为data_send()显示的x字符串是185个字符,没有空终止符。 So, if it is getting truncated, that could account for the ENOENT error you are getting. 因此,如果它被截断,那可能会导致您获得的ENOENT错误。

That being said, you are calculating the size of sockaddr_un incorrectly, and passing the wrong address size to bind() and sendto() . 话虽这么说,你正在错误地计算sockaddr_un的大小,并将错误的地址大小传递给bind()sendto() Also, open_and_bind_socket() and data_send() are leaking memory. 此外, open_and_bind_socket()data_send()正在泄漏内存。

Try something more like this instead: 尝试更像这样的东西:

int open_and_bind_socket(int *sockfd, const char *sname)
{
    *sockfd = -1;

    //sname is socket name with full path
    size_t len = strlen (sname);

    size_t size = offsetof (struct sockaddr_un, sun_path) + len + 1;

    struct sockaddr_un *unaddr = (struct sockaddr_un *) malloc (size);
    if (!unaddr)
    {
        AGENT_DEBUG(LOG_ERR, "%s", "Failed to allocate memory\n");
        return ~0;
    }

    memset(unaddr, 0, size);
    unaddr->sun_family = AF_UNIX;
    memcpy(unaddr->sun_path, sname, len);
    unaddr->sun_len = SUN_LEN(unaddr);

    int sock = socket (AF_LOCAL, SOCK_DGRAM, 0);
    if (sock < 0)
    {
        AGENT_DEBUG(LOG_ERR, "%s", "Failed to create socket: %s\n", strerror(errno));
        free(unaddr);
        return ~0;
    }

    if (bind(sock, (struct sockaddr*)unaddr, unaddr->sun_len) < 0)
    {
        AGENT_DEBUG(LOG_ERR, "%s", "Failed to bind the socket: %s\n", strerror(errno));
        close(sock);
        free(unaddr);
        return ~0;
    }

    if (0 != chmod(sname, 0666))
    {
        AGENT_DEBUG(LOG_ERR, "%s", "Unable to chmod socket: %s\n", strerror(errno));
        close(sock);
        free(unaddr);
        return ~0;
    }

    free(unaddr);

    //unlink(sname);

    *sockfd = sock;

    return 0;
}

int data_send(int sockfd, tsIpcMsg *pMsgData)
{
    // this is a buffer overflow waiting to happen!
    memset(x, '\0', sizeof(x));
    strcpy(x, buffer);
    strcat(x, "/AGENTSOCKET");

    size_t len = strlen (x);

    size_t size = offsetof (struct sockaddr_un, sun_path) + len + 1;

    struct sockaddr_un *saun = (struct sockaddr_un *) malloc (size);
    if (!saun)
    {
        AGENT_DEBUG(LOG_ERR, "%s", "Failed to allocate memory\n");
        return ~0;
    }

    memset(saun, 0, size);
    saun->sun_family = AF_UNIX;    
    memcpy(saun->sun_path, x, len);
    saun->sun_len = SUN_LEN(saun);

    if (sendto(sockfd, (void*)pMsgData, sizeof(tsIpcMsg) + pMsgData->dataLen, 0, (struct sockaddr *)saun, saun->sun_len) < 0)
    {
        AGENT_DEBUG(LOG_ERR, "%s", "Failed to send message from thread to main: %s\n", strerror(errno));
        free(saun);
        return ~0;
    }

    free(saun);
    return 0;
}

Alternatively, you do not need to dynamically allocate the sockaddr_un at all: 或者,您根本不需要动态分配sockaddr_un

int open_and_bind_socket(int *sockfd, const char *sname)
{
    *sockfd = -1;

    struct sockaddr_un unaddr;

    memset(&unaddr, 0, sizeof(unaddr));
    unaddr.sun_family = AF_UNIX;
    strncpy(unaddr.sun_path, sname, sizeof(unaddr.sun_path)-1);
    unaddr.sun_len = SUN_LEN(&unaddr);

    int sock = socket (AF_LOCAL, SOCK_DGRAM, 0);
    if (sock < 0)
    {
        AGENT_DEBUG(LOG_ERR, "%s", "Failed to create socket: %s\n", strerror(errno));
        return ~0;
    }

    if (bind(sock, (struct sockaddr*) &unaddr, unaddr.sun_len) < 0)
    {
        AGENT_DEBUG(LOG_ERR, "%s", "Failed to bind the socket: %s\n", strerror(errno));
        close(sock);
        return ~0;
    }

    if (0 != chmod(sname, 0666))
    {
        AGENT_DEBUG(LOG_ERR, "%s", "Unable to chmod socket: %s\n", strerror(errno));
        close(sock);
        return ~0;
    }

    //unlink(sname);

    *sockfd = sock;

    return 0;
}

int data_send(int sockfd, tsIpcMsg *pMsgData)
{
    // this is a buffer overflow waiting to happen!
    memset(x, '\0', sizeof(x));
    strcpy(x, buffer);
    strcat(x, "/AGENTSOCKET");

    struct sockaddr_un saun;

    memset(&saun, 0, sizeof(saun));
    saun.sun_family = AF_UNIX;    
    strncpy(saun.sun_path, x, sizeof(saun.sun_path)-1);
    // alternatively this is safer:
    // snprintf(saun.sun_path, sizeof(saun.sun_path), "%s/AGENTSOCKET", buffer); 
    saun.sun_len = SUN_LEN(&saun);

    if (sendto(sockfd, (void*)pMsgData, sizeof(*pMsgData) + pMsgData->dataLen, 0, (struct sockaddr *) &saun, saun.sun_len) < 0)
    {
        AGENT_DEBUG(LOG_ERR, "%s", "Failed to send message from thread to main: %s\n", strerror(errno));
        return ~0;
    }

    return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM