制作一个自己的对战平台

缘起

因为在浙大,物理网卡的地址被分配为222.205.XX.XX,但是子网掩码是255.255.255.0,这样的话虽然大家都在一个局域网里面,但是却不一定在同一个子网。
局域网联机游戏为了发现局域网中的主机,会发送广播包,有些局域网联机游戏,会发送到255.255.255.255这个广播地址(典型代表War3),但是这个广播地址
是只能广播到子网的,路由器默认不转发,这样就造成了我们同在校园网却无法联机的问题。

虚拟局域网

想了想解决方案,可能使用虚拟网卡做一个虚拟局域网是一个解决方案,于是我安装了OpenVPN,然后使用其tap0901网卡驱动,可以读取注册表
获取tap0901设备的实例UUID以及显示在网络和共享中心的那个网络名称:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}
这个里面有很多项,代表了多个网卡接口,其中会有一个是tuntap设备,通过类似这样的地址HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4d36e972-e325-11ce-bfc1-08002be10318}\0002下的ComponentIdtap0901来确定tap网卡,然后读取该项下面的netCfgInstanceId,就是tap网卡的UUID,得到这个UUID之后,
可以使用CreateFile函数来打开一个tuntap设备:

HANDLE f = CreateFile(L"\\\\.\\Global\\{...}", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, NULL);

打开这个设备后,就可以对其发送指令了,参照tuntap的驱动源代码tap-windows6,可以获得一些宏,以及一些指令的参数信息,然后使用
DeviceIoControl发送到设备:

DeviceIoControl(f, TAP_IOCTL_SET_MEDIA_STATUS, config, 4, config, 4, &returnLen, NULL);

启动tuntap设备之前,要考虑到单机游戏发送广播包,所以应该修改路由表,让255.255.255.255路由经过我们的tuntap设备,以及作为虚拟局域网,每个tuntap设备应该有一个虚拟ip,这里
假设为192.168.1.10。设置

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
这是一个比较复杂的项目,需要涉及到多个方面的知识和技能,包括游戏开发、网络编程等。以下是一个简单的示例代码,供参考: ``` #include <iostream> #include <winsock2.h> #include <windows.h> #pragma comment(lib, "ws2_32.lib") using namespace std; const int PORT = 8888; // 端口号 const int BUFFER_SIZE = 1024; // 缓冲区大小 void error(const char* msg) { cerr << msg << endl; exit(1); } int main() { // 初始化 Winsock 库 WSADATA wsaData; int ret = WSAStartup(MAKEWORD(2, 2), &wsaData); if (ret != 0) { error("WSAStartup failed"); } // 创建 socket SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (serverSocket == INVALID_SOCKET) { error("socket creation failed"); } // 绑定端口号 sockaddr_in serverAddr; memset(&serverAddr, 0, sizeof(serverAddr)); serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(PORT); serverAddr.sin_addr.s_addr = INADDR_ANY; ret = bind(serverSocket, (sockaddr*)&serverAddr, sizeof(serverAddr)); if (ret == SOCKET_ERROR) { error("bind failed"); } // 监听连接请求 ret = listen(serverSocket, SOMAXCONN); if (ret == SOCKET_ERROR) { error("listen failed"); } // 等待客户端连接 SOCKET clientSocket = accept(serverSocket, NULL, NULL); if (clientSocket == INVALID_SOCKET) { error("accept failed"); } // 接收数据 char buffer[BUFFER_SIZE]; while (true) { memset(buffer, 0, sizeof(buffer)); ret = recv(clientSocket, buffer, BUFFER_SIZE, 0); if (ret == SOCKET_ERROR) { error("recv failed"); } if (ret == 0) { break; } cout << "Received message: " << buffer << endl; } // 关闭 socket closesocket(clientSocket); closesocket(serverSocket); // 清理 Winsock 库 WSACleanup(); return 0; } ``` 这段代码实现了一个简单的服务器端,通过监听端口号等待客户端的连接请求,并能够接收客户端发送的消息。在实际开发中,还需要编写客户端程序,并在服务器端与客户端之间建立连接并传输游戏数据等信息。同时,还需要实现游戏逻辑、图形界面等功能,这些都需要比较多的代码和技能支持。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值