简述
一个验证游戏开发中,常用网络架构的demo
- 弱联网(http链接):排行榜功能
- 即时性较弱(基于tcp):多人大厅,聊天室
- 及时性强(基于udp):房间类,多人格斗
demo框架:
unity(URP + xlua + VMUI)
网络层使用udp,客户端使用xlua集成的luasocket,服务端使用c++
一 即时格斗部分(及时性)
概述
使用udp+帧同步,保证传输效率和准确性
服务端代码:
#include <Winsock2.h>
#include <cstdio>
#include <string.h>
#include <stdio.h>
#include<map>
#include <iostream>
using namespace std;
#pragma comment(lib,"ws2_32.lib")
#define bufsize 1024
#define UserNum 2 //玩家数量
int main()
{
//1 创建套接字 绑定端口
WSADATA wsaData;
SOCKET sockServer;
SOCKADDR_IN addrServer;
SOCKADDR_IN tempClientAddr;
map<SOCKADDR_IN, bool> strMap;
SOCKADDR_IN ClientAddrList[UserNum] ;
int str_len ;
char message[bufsize] = "\0";
int nRet;
int len = sizeof(SOCKADDR);
WSAStartup(MAKEWORD(2, 2), &wsaData);
sockServer = socket(AF_INET, SOCK_DGRAM, 0);
addrServer.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//INADDR_ANY表示任何IP
addrServer.sin_family = AF_INET;
addrServer.sin_port = htons(6000);//绑定端口6000
nRet = bind(sockServer, (SOCKADDR*)&addrServer, sizeof(SOCKADDR));
if (SOCKET_ERROR == nRet)
{
printf("bind failed !/n");
closesocket(sockServer);
WSACleanup();
return -1;
}
int key = 0;
//2 进入循环接收玩家信息 与发送信息
printf("服务器已启动udp:\n监听中...\n");
while (true)
{
str_len = recvfrom(sockServer, message, bufsize, 0, (SOCKADDR*)&tempClientAddr, &len);
if (SOCKET_ERROR != str_len )
{
printf("recv 读入玩家id: %d \n", key);
ClientAddrList[key] = tempClientAddr;
}
for (int i = 0; i < UserNum; i++)
{
str_len = sendto(sockServer, message, bufsize, 0, (SOCKADDR*)&ClientAddrList[i], len);
if (SOCKET_ERROR != str_len)
{
printf("send 发送至玩家id: %s\n", message);
}
}
}
WSACleanup();
}
客户端代码:
-- Assets\LuaScripts\FrameWrok\net\networkmanger.lua
--------------------------------------------
-- @协议 使用udp
--1
function SocketInit()
_G["G_SOCKETTCP"] = require("socket.core").udp()
_G["G_SOCKETTCP"]:settimeout(0)
SocketSend("20180625")
end
function SocketClose()
_G["G_SOCKETTCP"]:close()
end
function SocketSend(sendStr)
print("[c->s]:".. sendStr)
local sendstr = _G["G_SOCKETTCP"]:sendto(sendStr, "127.0.0.1", 6000)
end
function SocketReceive(callfun)
if nil == _G["G_SOCKETTCP"] then return end
local response, receive_status = _G["G_SOCKETTCP"]:receive()
if receive_status ~= "closed" then
if response then
print("[s->c]:".. response)
callfun(response)
end
else
print("Service Closed!")
end
end
-- Assets\LuaScripts\FrameWrok\funcTest.lua
local test = {}
---- 网络模块测试 ----
print("网络模块测试------------->Socket")
require("FrameWrok.net.networkmanger")
SocketInit()
SocketSend("player1")
test.update = function ()
SocketReceive(function (command_str)
-- print("SocketReceive command_str------------>" .. command_str)
end)
end
-- SocketClose()
---- end 网络模块测试 ----
return test