Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Windows主机和Linux来宾之间使用Hyper-V套接字_Linux_Windows_Sockets_Hyper V - Fatal编程技术网

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

在Windows主机和Linux来宾之间使用Hyper-V套接字,linux,windows,sockets,hyper-v,Linux,Windows,Sockets,Hyper V,我想编写一个简单的应用程序,使用Hyper-V套接字netcat over vsock在Hyper-V主机及其虚拟机之间进行通信。在互联网上有一些文件描述了如何做到这一点:。然而,它们中的任何一个都能帮助我实现我的目标 首先,我已经确保使用Hyper-V套接字进行连接是可能的。在来宾Linux上,我加载了hv_sock模块并运行能够在VSock上侦听的应用程序: $sudo modprobe hv_短袜 $nc vsock-l 1234 在PowerShell中的Windows上,我运行了hvc

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

首先,我已经确保使用Hyper-V套接字进行连接是可能的。在来宾Linux上,我加载了hv_sock模块并运行能够在VSock上侦听的应用程序:

$sudo modprobe hv_短袜 $nc vsock-l 1234 在PowerShell中的Windows上,我运行了hvc,它使用Hyper-V套接字并能够模拟netcat:

hvc nc-t vsock小助手1234 它是有效的。我可以看到数据从服务器发送到客户端,反之亦然

然后,我编写了一个简单的应用程序,该应用程序基于并稍作修改。 如中所述,我在Hyper-V主机的注册表中注册了我的应用程序,并运行了我的应用程序。未建立连接,连接函数返回错误10049

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

在我看来,文件中有一些模棱两可之处。例如,据说服务id应该是一个随机GUID。但稍后需要注意的是,前四个八位字节转换为AF_VSOCK地址族中的端口,并为此提供了特定的GUID

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

完整代码:

包括 包括 包括 包括 包括 int main { 结构uuu declspecuuid00000000-185c-4e04-985a-4C2EE3E03CC VSockTemplate{}; 结构uuu declspecuuid2a9fa68e-4add-45cb-85c8-de97fc66d388 ServerVsockTemplate{}; //----------- //初始化Winsock WSADATA WSADATA; int-iResult=wsastartpmakeword2、2和wsaData; 如果iResult!=无错误{ wprintfLWSAStartup函数失败,错误为:%d\n,iResult; 返回1; } //----------- //创建用于连接到服务器的套接字 插座连接插座; ConnectSocket=socketAF\u HYPERV、SOCK\u流、HV\u协议\u RAW; 如果ConnectSocket==无效的\u套接字{ wprintfLsocket函数失败,错误:%ld\n,WSAGetLastError; WSACleanup; 返回1; } //----------- //结构中的sockaddr_指定地址族, //要连接到的服务器的IP地址和端口。 SOCKADDR_高压客户服务; clientService.Family=AF_HYPERV; clientService.VmId=\uuuuIdofservervsockTemplate; clientService.ServiceId=\uuuuIdoFvsockTemplate; clientService.ServiceId.Data1=1234; //----------- //连接到服务器。 iResult=connectsocket、SOCKADDR*&客户端服务、sizeofclientService; 如果iResult==SOCKET\u错误{ wprintfLconnect函数失败,错误:%ld\n,WSAGetLastError; iResult=closesocketConnectSocket; 如果iResult==SOCKET\u错误 wprintfLclosesocket函数失败,错误:%ld\n,WSAGetLastError; WSACleanup; 返回1; } WPRINTFL已连接到服务器。\n; iResult=closesocketConnectSocket; 如果iResult==SOCKET\u错误{ wprintfLclosesocket函数失败,错误:%ld\n,WSAGetLastError; WSACleanup; 返回1; } WSACleanup; 返回0; } 您的ServerVsockTemplate GUID是什么?我很确定这应该是正在运行的VM的GUID,例如Get VM-Name$VMName.Id,所以很难硬编码到源代码中。如果这是您根据生成的GUID,那么这就是问题所在

文档不清楚,但我强烈怀疑“注册新应用程序”部分仅适用于在Windows上侦听来自其他Windows虚拟机的传入连接时,或编写与主机上的服务对话的Linux设备驱动程序时。它也可能允许一个VM向其他VM提供服务,但我认为不会

Edit:表示您还需要为vsockguid创建注册表项,以便从vm接收连接

在Linux用户空间中,您只能访问vsock;在Linux下由驱动程序管理

在Linux源代码中,对于vsock工作流有一个更清晰的解释

当然,我假设在Windows虚拟机和主机之间也可以使用VSock

编辑,因为我确实去测试了这个

代码中有两个错误,ServerVsockTemplate GUID需要作为目标VM的GUID

VSockTemplate GUID错误。我不知道这是从哪里来的,但无论如何都有一个恒定的HV_GUID_VSOCK_模板,它与Microsoft文档网站上的模板匹配:00000000-facb-11e6-bd58-64006a7986d3 事实证明,您需要将 SOCKADDR_HV,否则它会失败。传统上,人们会使用memset将新的sockaddr_*结构归零,但在这种情况下,我们可以采取简单的方法。 因此,要实现这一点,请将SOCKADDR_HV创建代码更改为以下代码:

    // 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.Reserved = 0;
    clientService.VmId = __uuidof(ServerVsockTemplate);
    clientService.ServiceId = HV_GUID_VSOCK_TEMPLATE;
    clientService.ServiceId.Data1 = 1234;
然后删除VSockTemplate,并确保ServerVsockTemplate是运行nc vsock的VM或Micro VM的GUID

实际上,我用WSL2 micro虚拟机对此进行了测试,其虚拟机ID来自hcsdiag列表,而不是Get VM,但我能够在WSL2会话中使用这里的源连接到nc vsock,正如我所描述的那样进行了修改。

那里的ServerVsockTemplate GUID是什么?我很确定这应该是正在运行的VM的GUID,例如Get VM-Name$VMName.Id,所以很难硬编码到源代码中。如果这是您根据生成的GUID,那么这就是问题所在

文档不清楚,但我强烈怀疑“注册新应用程序”部分仅适用于在Windows上侦听来自其他Windows虚拟机的传入连接时,或编写与主机上的服务对话的Linux设备驱动程序时。它也可能允许一个VM向其他VM提供服务,但我认为不会

Edit:表示您还需要为vsockguid创建注册表项,以便从vm接收连接

在Linux用户空间中,您只能访问vsock;在Linux下由驱动程序管理

在Linux源代码中,对于vsock工作流有一个更清晰的解释

当然,我假设在Windows虚拟机和主机之间也可以使用VSock

编辑,因为我确实去测试了这个

代码中有两个错误,ServerVsockTemplate GUID需要作为目标VM的GUID

VSockTemplate GUID错误。我不知道这是从哪里来的,但无论如何都有一个恒定的HV_GUID_VSOCK_模板,它与Microsoft文档网站上的模板匹配:00000000-facb-11e6-bd58-64006a7986d3 事实证明,您需要将sockaddru HV的保留成员归零,否则它将失败。传统上,人们会使用memset将新的sockaddr_*结构归零,但在这种情况下,我们可以采取简单的方法。 因此,要实现这一点,请将SOCKADDR_HV创建代码更改为以下代码:

    // 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.Reserved = 0;
    clientService.VmId = __uuidof(ServerVsockTemplate);
    clientService.ServiceId = HV_GUID_VSOCK_TEMPLATE;
    clientService.ServiceId.Data1 = 1234;
然后删除VSockTemplate,并确保ServerVsockTemplate是运行nc vsock的VM或Micro VM的GUID


实际上,我用WSL2 micro虚拟机对此进行了测试,该虚拟机的虚拟机ID来自hcsdiag列表,而不是Get虚拟机,但我能够使用此处的源连接到WSL2会话中的nc vsock,如我所述进行了修改。

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

确保在客户机上启用了hv_sock内核模块,我使用的是Ubuntu服务器20.04,默认情况下没有启用

lsmod | grep hv|U短袜 如果不存在,则需要添加它并重新启动:

sudo sh-c'echo hv_sock>/etc/modules load.d/hv_sock.conf' sudo重启 您需要在Hyper-V主机的注册表中注册一个新的应用程序,但这些文档有误导性,因为随机GUID仅在Windows客户机中需要,对于Linux客户机,GUID需要采用非常特定的格式,如HV_GUID_VSOCK_模板所述,即-facb-11e6-bd58-64006a7986d3

因此,对于端口5001,注册表项应为00001389-facb-11e6-bd58-64006a7986d3 1389为十六进制的5001 如本节所述,您可以从powershell轻松完成此操作

$service=新项目-路径HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Virtualization\GuestCommunications Services-名称00001389-facb-11e6-bd58-64006a7986d3 $service.SetValueElementName,高压插座演示
您可以找到一些简单的代码示例,Windows主机为win_server.c,Linux来宾为wsl_client.c。

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

确保在客户机上启用了hv_sock内核模块,我使用的是Ubuntu服务器20.04,默认情况下没有启用

lsmod | grep hv|U短袜 如果不存在,则需要添加它并重新启动:

sudo sh-c'echo hv_sock>/etc/modules load.d/hv_sock.conf' sudo重启 您需要在Hyper-V主机的注册表中注册一个新的应用程序,但这些文档有误导性,因为随机GUID仅在Windows客户机中需要,对于Linux客户机,GUID需要采用非常特定的格式,如HV_GUID_VSOCK_模板所述,即-facb-11e6-bd58-64006a7986d3

因此,对于端口5001,注册表项应为00001389-facb-11e6-bd58-64006a7986d3 1389为十六进制的5001 如本节所述,您可以从powershell轻松完成此操作

$service=新项目-路径HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Virtualization\GuestCommunications Services-名称00001389-facb-11e6-bd58-64006a7986d3 $service.SetValueElementName,高压插座演示 你可以找到
一些简单的代码示例,Windows主机的win_server.c和Linux来宾的wsl_client.c。

关于注册Hyper-V主机注册表的步骤非常关键。节省了我很多时间。谢谢请注意,如果HvSocket服务器位于WSL端,而客户端位于Windows主机端,则不需要此步骤。有关注册Hyper-V主机注册表的步骤非常关键。节省了我很多时间。谢谢请注意,如果HvSocket服务器位于WSL端,而客户端位于Windows主机端,则不需要执行此步骤。