我正在使用抽象 Unix 套接字在 C 和 Go 程序之间传递数据。 C 程序正在创建套接字,Go 程序连接到它。问题是 Go 程序无法连接到套接字,我收到以下错误消息:
UDS connection failed: dial unixgram @uds-js: connect: connection refused
这是 C 程序:
#include <string.h> #include <sys/socket.h> #include <sys/un.h> #include <unistd.h> /* Buffer size for the receive socket */ #define BUFFER_SIZE 4096 /* The abstract Unix domain socket address name */ #define UDS_ADDRESS_NAME "#uds-js" int main() { int socket_fd; int bytes_received; char buffer[BUFFER_SIZE]; struct sockaddr_un server_address; struct sockaddr_un client_address; socklen_t address_length = sizeof(struct sockaddr_un); /* Create local unix socket */ if ( ( socket_fd = socket ( AF_UNIX, SOCK_DGRAM, 0 ) ) < 0 ) { printf ( "socket error\n" ); return 1; } /* Set an abstract socket address */ memset( &server_address, 0, sizeof(server_address) ); server_address.sun_family = AF_UNIX; strcpy( server_address.sun_path, UDS_ADDRESS_NAME ); server_address.sun_path[0] = '\0'; /* Bind socket to address */ if ( bind ( socket_fd, (const struct sockaddr *) &server_address, address_length ) < 0 ) { close ( socket_fd ); printf ( "socket bind error\n" ); return 1; } bytes_received = recvfrom( socket_fd, &buffer, BUFFER_SIZE, 0, (struct sockaddr *) &client_address, &address_length ); printf ( "Received: %s\n", buffer ); return 0; }
And the Go program:
import (
"fmt"
"net"
"os"
)
func main() {
addr, _ := net.ResolveUnixAddr("unixgram", "@uds-js")
udsSock, err := net.DialUnix("unixgram", nil, addr)
if err != nil {
fmt.Printf("UDS connection failed: %v\n", err)
os.Exit(1)
}
defer udsSock.Close()
if _, err := udsSock.Write([]byte("{\"test\":100}")); err != nil {
fmt.Printf("Failed to send message on UDS: %v\n", err)
}
}
在 C 程序中,我将套接字名称中的第一个字节设置为空字节,as to spec 。根据我收集的信息in Go该名称需要以 @
开头。
运行netstat
我可以看到套接字已创建:
$ netstat -ax | grep DGRAM
unix 2 [ ] DGRAM 12411992 @uds-js@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
为什么Go程序连接socket失败?
编辑:
将名称更改为路径名 /tmp/uds-js
,这确实可以按预期工作。
编辑2:
我用 Go 语言创建了一个服务器,用 C 语言为抽象套接字创建了一个客户端,这两个 C 程序和两个 Go 程序可以很好地协同工作。问题似乎出在使用抽象套接字从 C 转到 Go 时。
最佳答案
Go 程序连接到错误的抽象套接字(或者,等效地,C 程序绑定(bind)到错误的抽象套接字)。
您的bind()
是针对长度为sizeof(struct sockaddr_un)
的抽象命名空间UNIX套接字地址进行的。如果我是reading the Go implementation correctly但是,您的 connect()
是针对长度为 9 的套接字地址执行的:sa_family
为两个字节,在本例中为 len(名称)
。
这些是不同的套接字。
在抽象命名空间中,NULL 并不特殊,因此 "\0uds-js"
是一个有效的套接字地址,而 "\0uds-js\0\0\0\0\0\0\0\0..."
是一个不同的有效地址。
strace 两个进程都会查看 C 程序的 bind()
和 Go 程序的 connect()
。我希望您会看到它们使用不同的 socklen_t
参数调用这些函数。
关于c - C 和 Go 之间的抽象 Unix 套接字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62535276/