gpt4 book ai didi

linux - 在 Windows 主机和 Linux guest 之间使用 Hyper-V 套接字

转载 作者:行者123 更新时间:2023-12-03 12:02:54 25 4
gpt4 key购买 nike

我想编写一个简单的应用程序,使用 Hyper-V 套接字(netcat over vsock)在 Hyper-V 主机及其虚拟机之间进行通信。互联网上有一些文档描述了如何做到这一点:Make your own integration services , Practical Hyper-V socket communication 。然而,它们中的任何一个都可以帮助我实现我的目标。

首先,我已确保可以使用 Hyper-V 套接字进行连接。在 guest Linux 上,我加载了 hv_sock 模块并运行 nc-vsock能够监听 vsocks 的应用程序:

$ sudo modprobe hv_sock
$ nc-vsock -l 1234

在 Windows 上的 PowerShell 中,我运行了 hvc,它利用 Hyper-V 套接字并能够模拟 netcat:

hvc nc -t vsock little-helper 1234

并且它有效。我可以看到从服务器发送到客户端的数据,反之亦然。

然后我根据 1 编写了一个简单的应用程序和 2有轻微的变化。我在 Hyper-V 主机的注册表中注册了我的应用程序,如 1 中所述。我运行了我的应用程序。连接未建立,connect 函数返回错误 10049。

我尝试以管理员身份运行我的应用程序,并在源代码和 Hyper-V 主机注册表中操作 GUID。然而,没有任何帮助,应用程序总是报告错误 10049。

我认为文档中存在一些含糊之处。例如。据说服务ID应该是一个随机的GUID。但后来有一个注释,前四个八位字节转换为 AF_VSOCK 地址族中的端口,并且为此目的提供了特定的 GUID。

问题很简单:我做错了什么或误解了什么。是否可以在 Windows 和 Linux 之间利用 vsock 编写 netcat?

完整代码:

#include <iostream>

#include <winsock2.h>
#include <ws2tcpip.h>
#include <hvsocket.h>

#include <combaseapi.h>

int main()
{
struct __declspec(uuid("00000000-185c-4e04-985a-4c2eee3e03cc")) VSockTemplate {};
struct __declspec(uuid("2a9fa68e-4add-45cb-85c8-de97fc66d388")) ServerVsockTemplate {};

//----------------------
// Initialize Winsock
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR) {
wprintf(L"WSAStartup function failed with error: %d\n", iResult);
return 1;
}
//----------------------
// Create a SOCKET for connecting to server
SOCKET ConnectSocket;
ConnectSocket = socket(AF_HYPERV, SOCK_STREAM, HV_PROTOCOL_RAW);
if (ConnectSocket == INVALID_SOCKET) {
wprintf(L"socket function failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
//----------------------
// The sockaddr_in structure specifies the address family,
// IP address, and port of the server to be connected to.
SOCKADDR_HV clientService;
clientService.Family = AF_HYPERV;
clientService.VmId = __uuidof(ServerVsockTemplate);
clientService.ServiceId = __uuidof(VSockTemplate);
clientService.ServiceId.Data1 = 1234;

//----------------------
// Connect to server.
iResult = connect(ConnectSocket, (SOCKADDR*)&clientService, sizeof(clientService));
if (iResult == SOCKET_ERROR) {
wprintf(L"connect function failed with error: %ld\n", WSAGetLastError());
iResult = closesocket(ConnectSocket);
if (iResult == SOCKET_ERROR)
wprintf(L"closesocket function failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}

wprintf(L"Connected to server.\n");

iResult = closesocket(ConnectSocket);
if (iResult == SOCKET_ERROR) {
wprintf(L"closesocket function failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}

WSACleanup();
return 0;
}

最佳答案

对于那些不太熟悉 Hyper-V 并且不想像我一样花费 2 小时调试的人来说,有几点:

确保 guest 上启用了 hv_sock 内核模块,我使用的是 Ubuntu Server 20.04,默认情况下没有启用此功能。

lsmod | grep hv_sock

如果不存在,您需要添加它并重新启动:

sudo sh -c 'echo "hv_sock" > /etc/modules-load.d/hv_sock.conf'
sudo reboot

需要使用 Hyper-V 主机的注册表注册新应用程序,但文档具有误导性,因为仅 Windows guest 需要随机 GUID,对于 Linux guest ,GUID 需要为采用非常具体的格式,如HV_GUID_VSOCK_TEMPLATE所述,意思是<port>-facb-11e6-bd58-64006a7986d3

所以端口 5001注册表项应该是 00001389-facb-11e6-bd58-64006a7986d3 (1389 是十六进制的 5001)您可以通过 powershell 轻松完成此操作,如 Register a new application 中所述。部分

$service = New-Item -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Virtualization\GuestCommunicationServices" -Name "00001389-facb-11e6-bd58-64006a7986d3"
$service.SetValue("ElementName", "HV Socket Demo")

您可以找到一些简单的代码示例 herewin_server.c(适用于 Windows 主机)和 wsl_client.c(适用于 Linux guest )。

关于linux - 在 Windows 主机和 Linux guest 之间使用 Hyper-V 套接字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60696166/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com