Thank you for the remind.
For the Go side, I am using this package.
(Not sure if it is compatible with the latest Go. I am using a Go version before 1.0 for some reason I won't update. I changed this package a little bit to run with my old Go)
https://github.com/burke/zeus/blob/master/go/unixsocket/unixsocket_test.goBelow is send FD part.
func main () {
file, err := os.Open ("/home/yl/test")
if err != nil {
panic (err)
}
fd := file.Fd()
conn, err := net.Dial ("unix", "mysock")
usock := unixsocket.NewUsock (conn.(*net.UnixConn))
usock.WriteFD(fd)
conn.Close()
file.Close()
}
Below is the C part to receive FD. the recv_fd function is borrowed from
http://www.thomasstover.com/uds.html#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
int recv_fd(int socket)
{
int sent_fd, available_ancillary_element_buffer_space;
struct msghdr socket_message;
struct iovec io_vector[1];
struct cmsghdr *control_message = NULL;
char message_buffer[1];
char ancillary_element_buffer[CMSG_SPACE(sizeof(int))];
/* start clean */
memset(&socket_message, 0, sizeof(struct msghdr));
memset(ancillary_element_buffer, 0, CMSG_SPACE(sizeof(int)));
/* setup a place to fill in message contents */
io_vector[0].iov_base = message_buffer;
io_vector[0].iov_len = 1;
socket_message.msg_iov = io_vector;
socket_message.msg_iovlen = 1;
/* provide space for the ancillary data */
socket_message.msg_control = ancillary_element_buffer;
socket_message.msg_controllen = CMSG_SPACE(sizeof(int));
if(recvmsg(socket, &socket_message, MSG_CMSG_CLOEXEC) < 0)
return -1;
int i;
for (i=0; i<sizeof(socket_message); i++)
{
printf ("%u ", (char *)&socket_message + i);
}
printf("\n");
if(message_buffer[0] != 'F')
{
/* this did not originate from the above function */
return -1;
}
if((socket_message.msg_flags & MSG_CTRUNC) == MSG_CTRUNC)
{
/* we did not provide enough space for the ancillary element array */
return -1;
}
/* iterate ancillary elements */
for(control_message = CMSG_FIRSTHDR(&socket_message);
control_message != NULL;
control_message = CMSG_NXTHDR(&socket_message, control_message))
{
if( (control_message->cmsg_level == SOL_SOCKET) &&
(control_message->cmsg_type == SCM_RIGHTS) )
{
sent_fd = *((int *) CMSG_DATA(control_message));
return sent_fd;
}
}
return -1;
}
int main()
{
int rv, lsock, sock;
struct sockaddr_un local;
struct sockaddr remote;
if ((lsock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
{
perror ("socket failed");
exit (lsock);
}
local.sun_family = AF_UNIX;
strcpy (local.sun_path, "mysock");
unlink (local.sun_path);
int len = strlen (local.sun_path) + sizeof(local.sun_family);
if ((rv = bind(lsock, (struct sockaddr *)&local, len)) < 0)
{
perror ("bind error");
exit (rv);
}
if ((rv = listen(lsock, 50)) < 0)
{
perror ("listen error");
exit (rv);
}
unsigned int length = sizeof (struct sockaddr_un);
if ((sock = accept(lsock, &remote, &length)) < 0)
{
perror ("accept error");
exit (sock);
}
int fd = recv_fd (sock);
FILE *fp = fdopen (fd, "r");
char buf[100];
buf[99] = '\0';
fscanf (fp, "%s", buf);
printf("Read from file: %s\n", buf);
fclose (fp);
close (sock);
close (lsock);
return 0;