从 iOS 扩展中绑定 Unix 域套接字失败,错误号为 48(地址已在使用中)

Binding a Unix Domain Socket from within an iOS extension fails with errno 48 (Address already in use)

我有一些逻辑可以通过创建 Unix 域套接字来工作,并且在 运行 普通应用程序中没有任何问题。但是,当我 运行 这是一个应用程序扩展时,我从 bind().

得到一个 -1 和 errno = 48 ("Address already in use")
NSArray *applicationSupportDirectoryPaths = 
NSSearchPathForDirectoriesInDomains(NSLibraryDirectory,
                                    NSUserDomainMask, YES);

int fd = socket(AF_UNIX, SOCK_STREAM, 0); // returns a non-zero value

NSString *loc = [applicationSupportDirectoryPaths[0] stringByAppendingPathComponent:@"usd"];
struct sockaddr_un addr;
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX   ;
strncpy(addr.sun_path, [loc UTF8String], sizeof(addr.sun_path)-1);
int bindres = bind(fd, (struct sockaddr*)&addr, sizeof(addr)); // returns -1, error is 48

为库目录返回的位置是:

/var/mobile/Containers/Data/PluginKitPlugin/A8110BA2-5AE7-42C1-84DA-2A9B303C7277/Library/

我认为失败的原因是因为与应用程序的库目录相比,这是一些特殊的位置。

如果有人知道为什么会发生这种情况或有任何解决方法,我将不胜感激。

更新:我尝试使用缓存目录 (NSCachesDirectory),但现在我得到错误号 3(没有这样的过程)。

初步猜测地址确实在使用中。

iOS 可能会 instantiate/kill 按需扩展,因此在执行下一次调用时可能不会释放上一次调用中绑定的套接字。

我觉得你应该先释放第一个对象,然后再调用下一个。

如果要强制绑定新套接字,可以使用SO_REUSEADDR套接字选项。

您可以使用如下的setsockopt()来设置SO_REUSEADDR。

int reuse = 1;

if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse)) < 0)
{
    perror("setsockopt(SO_REUSEADDR) failed");
}