Sending message to Windows Mailslot with Go // 使用Go语言向Windows Mailslot邮槽发送消息
最近在工作中的一个项目遇到了需要向Windows中的Mailslot(邮槽)发送消息的需求。因为我们的程序是用Go语言写的,之前有使用过Named Pipes来实现Windows平台上的IPC,使用的是go-winio库,但是这个库里面没有针对Mailslot的支持。作为不会写C/C++的我,本身想着用一个简单的程序作为中间件,监听一个Named Pipe来转发消息到Mailslot,毕竟这种简单的例子Google一下一大堆的。
然后做好了之后,我仔(wu)细(liao)看了一下C里面向Mailslot发送消息的代码
int send(char const *msg)
{
HANDLE sHandle;
DWORD bWritten;
if ((sHandle = CreateFile(
SlotName,
GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL)) == INVALID_HANDLE_VALUE)
{
printf("CreateFile failed with error %d\n", GetLastError());
return GetLastError();
}
if (WriteFile(sHandle, msg, strlen(msg), &bWritten, NULL) == 0)
{
printf("WriteFile failed with error %d\n", GetLastError());
return GetLastError();
}
CloseHandle(sHandle);
return 0;
}
咦,是不是可以用syscall
来做这个事情?
package main
import (
"errors"
"fmt"
"syscall"
)
func main() {
n, err := Write(`\\.\mailslot\destination`, []byte("hello world!"))
if err != nil {
panic(err)
}
fmt.Printf("%d bytes written to mailslot\n", n)
}
func Write(mailslotPath string, message []byte) (int, error) {
pathPtr, _ := syscall.UTF16PtrFromString(mailslotPath)
h, err := syscall.CreateFile(pathPtr,
syscall.GENERIC_WRITE,
syscall.FILE_SHARE_READ,
&syscall.SecurityAttributes{},
syscall.OPEN_EXISTING,
syscall.FILE_ATTRIBUTE_NORMAL,
0)
if err != nil {
fmt.Printf("Failed to connect to mailslot: %s\n", err)
return -1, err
}
if h == syscall.InvalidHandle {
return -1, errors.New("invalid handle")
}
defer syscall.CloseHandle(h)
return syscall.Write(h, message)
}
可以看到,syscall.CreateFile
和C里面的CreateFile
参数接受的参数是一致的,连里面一些constant的参数名都是一样。真tm方便。
Read other posts