如何在Objective-C中使用本地域套接字
Objective-C使网络套接字与流一起使用变得非常容易,可以执行以下操作:如何在Objective-C中使用本地域套接字,objective-c,macos,sockets,networking,Objective C,Macos,Sockets,Networking,Objective-C使网络套接字与流一起使用变得非常容易,可以执行以下操作: // Setup comms with the server, assumed to be running on the local host NSHost* host = [NSHost hostWithAddress:@"127.0.0.1"]; NSInputStream *iStream; NSOutputStream *oStream; [NSStream getStreamsToHost:host p
// Setup comms with the server, assumed to be running on the local host
NSHost* host = [NSHost hostWithAddress:@"127.0.0.1"];
NSInputStream *iStream;
NSOutputStream *oStream;
[NSStream getStreamsToHost:host port:_PORT inputStream: &iStream outputStream: &oStream];
但是,是否可以通过这种方式创建和/或连接到,或者Objective-C是否为此提供了其他类
如果我仍然可以使用NSStream和getStreamsToHost,我将如何指定该文件以及端口号
到目前为止,我在这方面的研究显示了许多使用TCP/IP或UDP的示例,但不是本地域套接字。对于UNIX域套接字,您不能使用
-getStreamsToHost:port:inputStream:outputStream:
。但是,您可以创建自己的NSInputStream
和NSOutputStream
实例;最简单的方法是利用CF(读|写)流
和NS(输入|输出)流
之间的免费桥接;例如:
struct sockaddr_un sun;
sun.sun_family = AF_UNIX;
strcpy (sun.sun_path, "/path/to/my/socket");
sun.sun_len = SUN_LEN(&sun);
// Server side (naive)
int server_sock = socket (SOCK_UNIX, SOCK_STREAM, 0);
int ret = bind (server_sock, (struct sockaddr *)&sun, sun.sun_len);
listen (server_sock, 1); // In practice you'd specify more than 1
s = accept (server_sock, NULL, NULL); // In practice you want to keep calling this
// Client side
int s = socket (SOCK_UNIX, SOCK_STREAM, 0);
int ret = connect (s, (struct sockaddr *)&sun, sun.sun_len);
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocket (kCFAllocatorDefault, s, &readStream, &writeStream);
然后,要获得NSInputStream
和NSOutputStream
,只需执行以下操作即可
NSInputStream *inputStream = (__bridge_transfer NSInputStream *)readStream;
NSOutputStream *outputStream = (__bridge_transfer NSOutputSteram *)outputStream;
显然,在实践中,您可能希望在自己的代码中将上述所有内容封装在函数或方法中。另外,请注意sockaddr_un
;sun_path
成员可能应该有1024个字符,但在标题中似乎只有104个字符(这是一个长期存在的问题,显然要追溯到BSD4.4;有些系统也有其他字符计数)。这离PATH\u MAX还差得远,因此在实践中,您可能希望编写类似的代码
struct sockaddr_un *new_unix_addr (const char *path) {
size_t len = strlen (path);
size_t bytes = sizeof (struct sockaddr_un) + len + 1
- sizeof (((struct sockaddr_un *)0)->sun_path);
struct sockaddr_un *pun = (struct sockaddr_un *)malloc (bytes);
pun->sun_family = AF_UNIX;
pun->sun_len = bytes;
memcpy (pun->sun_path, path, len + 1);
return pun;
}
稍后请记住释放它。我不确定在
sun\u path
的定义中1024是否意外变成104,在其他平台(Linux、Solaris)上也是104或108。比较一下。@MartinR看起来这是一个很老的意外,然后:-)Unix域套接字可能在Unix系统中允许这么长的路径名之前就存在了。-我也不确定你是否可以简单地分配一个更大的sockaddr_un(你试过了吗?)。这需要内核能够处理更大的路径。POSIX规范声明“应用程序不应该假定sun_path的特定长度,或者假定它可以容纳{u POSIX_path_MAX}个字符(255)。@MartinR没有尝试过它,但我希望如果内核不支持它,它会失败并产生错误代码,这比缓冲区溢出要好。如果它真的支持它,那么它就会起作用。这似乎是一个合理的选择。谢谢,这一切看起来都不错,尽管我在连接到创建的套接字时遇到了问题。我以前用Qt编写过一个程序,它可以创建我可以连接的套接字。该套接字文件具有sxrwxrw-rw-权限,但您发布的代码创建的文件具有srwxr-xr-x权限。两个套接字都属于同一用户和组。我无法远程登录到由上述代码创建的套接字,因为它声明权限被拒绝。你知道为什么权限不同吗?即使我将文件chmod到777,它仍然无法允许连接。