📄 net.cpp
字号:
#include "graphics.h"
GUID LIB_GUID = {0x58fa98e0, 0x1999, 0x0507, {0x42, 0x01, 0x06, 0x74, 0x10, 0x16, 0x77, 0x30}};
LPDIRECTPLAY4A lpDP = NULL; // DirectPlay对象
LPDIRECTPLAYLOBBY3A lpDPL = NULL; // DirectPlayLobby对象
DPID DirectPlayID; // DirectPlay的ID
LPGUID lpGUID; // 游戏标识
BOOL IsHost = FALSE; // 是否为主机
BOOL NetInit = FALSE; // 网络正常标志
DPID PlayerID = NULL; // 玩家标志
DWORD DP_Thread_ID;
LIST *ListSP = NULL; // 建立连接类型列表
LIST *ListSession = NULL; // 会话列表
LIST *ListPlayer = NULL; // 玩家列表
LPVOID tcpip = NULL, modem = NULL, serial = NULL;
HANDLE PlayerEvent, ExitEvent, DP_Thread = NULL;
NETSESSION entry_session; // 当前的会话的属性
DPCAPS dpcaps; // DirectPlay的通信能力
BOOL CALLBACK EnumConnectionsCallback(LPCGUID lpGuid, LPVOID lpConnection, DWORD dwConnectionSize,
LPCDPNAME lpName, DWORD dwFlags, LPVOID lpContext);
BOOL CALLBACK EnumSessionsCallback(LPCDPSESSIONDESC2 lpThisSD, LPDWORD lpdwTimeOut, DWORD dwFlags, LPVOID lpContext);
BOOL CALLBACK EnumPlayersCallback(DPID dpID, DWORD dwPlayerType, LPCDPNAME lpName, DWORD dwFlags, LPVOID lpContext);
int (* NetMessageProc)(NETMESSAGE *);
DWORD WINAPI ReceiveMessage(LPVOID p);
// 初始化DirectPlay
BOOL init_directplay()
{
// 初始化DirectPlay对象
CoInitialize(NULL);
if (FAILED(CoCreateInstance(CLSID_DirectPlay, NULL, CLSCTX_INPROC_SERVER, IID_IDirectPlay4A, (LPVOID *)&lpDP)))
return FALSE;
if (FAILED(CoCreateInstance(CLSID_DirectPlayLobby, NULL, CLSCTX_INPROC_SERVER, IID_IDirectPlayLobby3A, (LPVOID *)&lpDPL)))
return FALSE;
ListSP = create_list();
lpDP->EnumConnections(&LIB_GUID, EnumConnectionsCallback, hWnd, 0);
PlayerEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
ExitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
DP_Thread = CreateThread(NULL, 0, ReceiveMessage, NULL, 0, &DP_Thread_ID);
if (DP_Thread == NULL)
return 0;
entry_session.lpguid = new GUID;
NetInit = TRUE;
return TRUE;
}
// 枚举连接类型
BOOL CALLBACK EnumConnectionsCallback(LPCGUID lpGuid, LPVOID lpConnection, DWORD dwConnectionSize,
LPCDPNAME lpName, DWORD dwFlags, LPVOID lpContext)
{
CONNECT_TYPE *ct;
ct = new CONNECT_TYPE;
if (ct == NULL)
return FALSE;
strcpy(ct->name, lpName->lpszShortNameA);
ct->size = dwConnectionSize;
ct->connect = new char [dwConnectionSize];
memcpy(ct->connect, lpConnection, dwConnectionSize);
if (IsEqualGUID(*lpGuid, DPSPGUID_TCPIP))
ct->type = CONNECT_TCPIP;
else if (IsEqualGUID(*lpGuid, DPSPGUID_IPX))
ct->type = CONNECT_IPX;
else if (IsEqualGUID(*lpGuid, DPSPGUID_MODEM))
ct->type = CONNECT_MODEM;
else if (IsEqualGUID(*lpGuid, DPSPGUID_SERIAL))
ct->type = CONNECT_SERIAL;
add_point(ListSP, ct);
return TRUE;
}
// 释放DirectPlay对象
void free_directplay()
{
LIST_POINT *p;
if (ListSP != NULL)
{
seek_to_first(ListSP);
while(ListSP->entry != NULL)
{
p = ListSP->entry;
ListSP->entry = ListSP->entry->next;
CONNECT_TYPE *ct;
ct = (CONNECT_TYPE *)(((LIST_POINT *)p)->data);
delete ct->connect;
delete ct;
delete p;
}
}
if (ListSession != NULL)
{
seek_to_first(ListSession);
while(ListSession->entry != NULL)
{
p = ListSession->entry;
ListSession->entry = ListSession->entry->next;
NETSESSION *ns;
ns = (NETSESSION *)(((LIST_POINT *)p)->data);
delete ns->lpguid;
delete p;
}
}
CloseHandle(PlayerEvent);
delete entry_session.lpguid;
lpDP->Release();
lpDP = NULL;
lpDPL->Release();
lpDPL = NULL;
}
// 初始化连接
BOOL init_connect(int type)
{
seek_to_first(ListSP);
for (DWORD i = 0; i < ListSP->count; i++)
{
CONNECT_TYPE *ct;
ct = (CONNECT_TYPE *)(ListSP->entry->data);
if (ct->type == type)
{
LPVOID lpdata = NULL;
switch(type)
{
case CONNECT_TCPIP:
lpdata = tcpip;
break;
case CONNECT_MODEM:
lpdata = modem;
break;
case CONNECT_SERIAL:
lpdata = serial;
}
if (lpdata == NULL)
{
if (FAILED(lpDP->InitializeConnection(ct->connect, 0)))
continue;
}
else
{
if (FAILED(lpDP->InitializeConnection(lpdata, 0)))
if (FAILED(lpDP->InitializeConnection(ct->connect, 0)))
continue;
}
dpcaps.dwSize = sizeof(dpcaps);
lpDP->GetCaps(&dpcaps, 0);
return TRUE;
}
seek_to_next(ListSP);
}
return FALSE;
}
// 建立一个会话
BOOL create_session(int max_play, char *name)
{
DPSESSIONDESC2 dpsd;
ZeroMemory(&dpsd, sizeof(DPSESSIONDESC2));
dpsd.dwSize = sizeof(DPSESSIONDESC2);
dpsd.dwFlags = DPSESSION_MIGRATEHOST | DPSESSION_KEEPALIVE;
dpsd.guidApplication = LIB_GUID;
dpsd.dwMaxPlayers = max_play;
dpsd.lpszSessionNameA = name;
if (FAILED(lpDP->Open(&dpsd, DPOPEN_CREATE)))
return FALSE;
*(entry_session.lpguid) = dpsd.guidInstance;
entry_session.maxplayer = dpsd.dwMaxPlayers;
strcpy(entry_session.name, name);
IsHost = TRUE;
return TRUE;
}
// 加入一个会话
BOOL join_session(char *name)
{
if (ListSession == NULL)
return FALSE;
seek_to_first(ListSession);
for (DWORD i = 0; i < ListSession->count; i++)
{
if (strcmp(name, ((NETSESSION *)(ListSession->entry->data))->name) == 0)
{
DPSESSIONDESC2 dpsd;
ZeroMemory(&dpsd, sizeof(dpsd));
dpsd.dwSize = sizeof(dpsd);
dpsd.guidInstance = *(((NETSESSION *)(ListSession->entry->data))->lpguid);
if (FAILED(lpDP->Open(&dpsd, DPOPEN_JOIN)))
return FALSE;
*(entry_session.lpguid) = dpsd.guidInstance;
entry_session.maxplayer = dpsd.dwMaxPlayers;
strcpy(entry_session.name, name);
return TRUE;
}
seek_to_next(ListSession);
}
return FALSE;
}
BOOL CALLBACK EnumSessionsCallback(LPCDPSESSIONDESC2 lpThisSD, LPDWORD lpdwTimeOut, DWORD dwFlags, LPVOID lpContext)
{
if (lpThisSD == NULL)
return FALSE;
NETSESSION *ns = new NETSESSION;
if (ns == NULL)
return FALSE;
strcpy(ns->name, lpThisSD->lpszSessionNameA);
ns->maxplayer = lpThisSD->dwMaxPlayers;
ns->lpguid = new GUID;
if (ns->lpguid == NULL)
return FALSE;
*(ns->lpguid) = lpThisSD->guidInstance;
add_point(ListSession, ns);
return TRUE;
}
// 枚举当前的会话
BOOL enum_session()
{
if (ListSession != NULL)
free_list(&ListSession);
ListSession = create_list();
DPSESSIONDESC2 dpsd;
ZeroMemory(&dpsd, sizeof(DPSESSIONDESC2));
dpsd.dwSize = sizeof(dpsd);
dpsd.guidApplication = LIB_GUID;
if (lpDP->EnumSessions(&dpsd, 0, EnumSessionsCallback, 0, DPENUMSESSIONS_ASYNC | DPENUMSESSIONS_AVAILABLE | DPENUMSESSIONS_RETURNSTATUS) != DP_OK)
return FALSE;
if (ListSession->count <= 0)
return FALSE;
return TRUE;
}
// 设置TCP/IP连接的IP地址
void set_net_ip(char *address)
{
DPCOMPOUNDADDRESSELEMENT dpcp[2];
DWORD size = 0;
if (tcpip)
{
delete tcpip;
tcpip = NULL;
}
dpcp[0].guidDataType = DPAID_ServiceProvider;
dpcp[0].dwDataSize = sizeof(GUID);
dpcp[0].lpData = (LPVOID)&DPSPGUID_TCPIP;
dpcp[1].guidDataType = DPAID_INet;
dpcp[1].dwDataSize = strlen(address) + 1;
dpcp[1].lpData = address;
lpDPL->CreateCompoundAddress(dpcp, 2, NULL, &size);
tcpip = new char [size];
if (tcpip == NULL)
return;
if (FAILED(lpDPL->CreateCompoundAddress(dpcp, 2, tcpip, &size)))
{
delete tcpip;
tcpip = NULL;
}
}
// 设置用Modem连接的电话号码
void set_net_phone(char *phone)
{
DPCOMPOUNDADDRESSELEMENT dpcp[2];
DWORD size = 0;
if (modem)
{
delete modem;
modem = NULL;
}
dpcp[0].guidDataType = DPAID_ServiceProvider;
dpcp[0].dwDataSize = sizeof(GUID);
dpcp[0].lpData = (LPVOID)&DPSPGUID_MODEM;
dpcp[1].guidDataType = DPAID_Phone;
dpcp[1].dwDataSize = strlen(phone) + 1;
dpcp[1].lpData = phone;
lpDPL->CreateCompoundAddress(dpcp, 2, NULL, &size);
modem = new char [size];
if (modem == NULL)
return;
if (FAILED(lpDPL->CreateCompoundAddress(dpcp, 2, modem, &size)))
{
delete modem;
modem = NULL;
}
}
// 设置串行口连接的参数
void set_net_port(int port, int speed)
{
DPCOMPORTADDRESS comport = {port, CBR_115200, ONESTOPBIT, NOPARITY, DPCPA_RTSFLOW};
DPCOMPOUNDADDRESSELEMENT dpcp[2];
DWORD size = 0;
if (serial)
{
delete serial;
serial = NULL;
}
switch(speed)
{
case 256000:
comport.dwBaudRate = CBR_256000;
break;
case 128000:
comport.dwBaudRate = CBR_128000;
break;
case 115200:
comport.dwBaudRate = CBR_115200;
break;
case 57600:
comport.dwBaudRate = CBR_57600;
break;
case 56000:
comport.dwBaudRate = CBR_56000;
break;
case 38400:
comport.dwBaudRate = CBR_38400;
break;
case 19200:
comport.dwBaudRate=CBR_19200;
break;
case 14400:
comport.dwBaudRate = CBR_14400;
}
dpcp[0].guidDataType = DPAID_ServiceProvider;
dpcp[0].dwDataSize = sizeof(GUID);
dpcp[0].lpData = (LPVOID)&DPSPGUID_SERIAL;
dpcp[1].guidDataType = DPAID_ComPort;
dpcp[1].dwDataSize = sizeof(comport);
dpcp[1].lpData = (LPVOID)&comport;
lpDPL->CreateCompoundAddress(dpcp, 2, NULL, &size);
serial = new char [size];
if (serial == NULL)
return;
if (FAILED(lpDPL->CreateCompoundAddress(dpcp, 2, serial, &size)))
{
delete serial;
serial = NULL;
}
}
// 建立一个玩家
BOOL create_player(char *name, char *namel, LPVOID lpdata, DWORD size)
{
DPNAME dpname;
ZeroMemory(&dpname,sizeof(dpname));
dpname.dwSize=sizeof(dpname);
dpname.lpszShortNameA=name;
dpname.lpszLongNameA=namel;
if (FAILED(lpDP->CreatePlayer(&PlayerID, &dpname, PlayerEvent, NULL, 0, 0)))
return FALSE;
return TRUE;
}
BOOL CALLBACK EnumPlayersCallback(DPID dpID, DWORD dwPlayerType, LPCDPNAME lpName, DWORD dwFlags, LPVOID lpContext)
{
PLAYER *py = new PLAYER;
if (py == NULL)
return FALSE;
py->playerid = dpID;
py->type = dwPlayerType;
if (lpName->lpszShortNameA == NULL)
*py->names = NULL;
else
strcpy(py->names, lpName->lpszShortNameA);
if (lpName->lpszLongNameA == NULL)
*py->namel = NULL;
else
strcpy(py->namel, lpName->lpszLongNameA);
add_point(ListPlayer, py);
return TRUE;
}
// 枚举玩家
BOOL enum_player()
{
if (ListPlayer != NULL)
free_list(&ListPlayer);
ListPlayer = create_list();
if (FAILED(lpDP->EnumPlayers(entry_session.lpguid, EnumPlayersCallback, NULL, 0)))
return FALSE;
return TRUE;
}
// 接收消息的进程
DWORD WINAPI ReceiveMessage(LPVOID p)
{
while(TRUE)
{
DPID idfrom, idto;
LPVOID buffer = NULL;
DWORD size = 0,bs = 1024;
LPDPMSG_GENERIC lpmsg;
LPDPMSG_CHAT chat;
LPDPMSG_CREATEPLAYERORGROUP createplayer;
LPDPMSG_DESTROYPLAYERORGROUP destplayer;
LPDPMSG_SETPLAYERORGROUPNAME setname;
LPDPMSG_SETSESSIONDESC sessiondesc;
NETMESSAGE netmsg;
HRESULT err;
HANDLE e[2] = {PlayerEvent, ExitEvent};
buffer = new char [1024];
if (buffer == NULL)
return -1;
while(WaitForMultipleObjects(2, e, FALSE, INFINITE) == WAIT_OBJECT_0)
{
idfrom = idto = 0;
size = bs;
err = lpDP->Receive(&idfrom, &idto, DPRECEIVE_ALL, buffer, &size);
while(err == DPERR_BUFFERTOOSMALL)
{
if (buffer)
delete buffer;
buffer = new char [size];
if (buffer == NULL)
return -1;
bs=size;
err = lpDP->Receive(&idfrom, &idto, DPRECEIVE_ALL, buffer, &size);
}
if(idfrom == DPID_SYSMSG)
{
lpmsg = (DPMSG_GENERIC *)buffer;
switch(lpmsg->dwType)
{
case DPSYS_CHAT:
chat = (DPMSG_CHAT *)buffer;
netmsg.type = NETDSYS_CHAT;
netmsg.idfrom = chat->idFromPlayer;
netmsg.idto = chat->idToPlayer;
netmsg.message = chat->lpChat->lpszMessageA;
break;
case DPSYS_CREATEPLAYERORGROUP:
createplayer = (DPMSG_CREATEPLAYERORGROUP *)buffer;
netmsg.type = NETDSYS_CREATEPLAYER;
netmsg.idfrom = createplayer->dpId;
netmsg.currentplayer = createplayer->dwCurrentPlayers;
netmsg.shortname = createplayer->dpnName.lpszShortNameA;
netmsg.longname = createplayer->dpnName.lpszLongNameA;
break;
case DPSYS_DESTROYPLAYERORGROUP:
destplayer = (DPMSG_DESTROYPLAYERORGROUP *)buffer;
netmsg.type = NETDSYS_DESTROYPLAYER;
netmsg.idfrom = destplayer->dpId;
break;
case DPSYS_HOST:
netmsg.type=NETDSYS_HOST;
break;
case DPSYS_SESSIONLOST:
netmsg.type = NETDSYS_SESSIONLOST;
break;
case DPSYS_SETPLAYERORGROUPNAME:
setname = (DPMSG_SETPLAYERORGROUPNAME *)buffer;
netmsg.type = NETDSYS_PLAYERNAME;
netmsg.idfrom = setname->dpId;
netmsg.shortname = setname->dpnName.lpszShortNameA;
netmsg.longname = setname->dpnName.lpszLongNameA;
break;
case DPSYS_SETSESSIONDESC:
sessiondesc = (DPMSG_SETSESSIONDESC *)buffer;
netmsg.type = NETDSYS_SESSIONDESC;
netmsg.desc = &sessiondesc->dpDesc;
break;
default:
case DPSYS_SENDCOMPLETE:
netmsg.type = NETDSYS_SEND;
continue;
}
}
else
{
netmsg.type = NETDSYS_USERMSG;
netmsg.data = buffer;
netmsg.size = size;
}
if (NetMessageProc)
NetMessageProc(&netmsg);
}
return 0;
}
return 0;
}
// 发送数据
BOOL send_data(NETMESSAGE *netmsg)
{
if (dpcaps.dwFlags & DPCAPS_ASYNCSUPPORTED)
if (FAILED(lpDP->SendEx(PlayerID, netmsg->idto, DPSEND_ASYNC, netmsg->data, netmsg->size, 0, 0, NULL, NULL)))
return FALSE;
else
if (FAILED(lpDP->SendEx(PlayerID, netmsg->idto, 0, netmsg->data, netmsg->size, 0, 0, NULL, NULL)))
return FALSE;
return TRUE;
}
// 发送对话消息
BOOL send_chat(NETMESSAGE *netmsg)
{
DPCHAT chat= {sizeof(DPCHAT), 0, NULL};
chat.lpszMessageA = netmsg->message;
if (FAILED(lpDP->SendChatMessage(PlayerID, netmsg->idto, 0, &chat)))
return FALSE;
return TRUE;
}
// 设置玩家名称
BOOL set_player_name(char * names, char * namel)
{
DPNAME dpname;
dpname.dwSize = sizeof(dpname);
dpname.dwFlags = 0;
dpname.lpszShortNameA = names;
dpname.lpszLongNameA = namel;
if (FAILED(lpDP->SetPlayerName(PlayerID, &dpname, DPSET_REMOTE)))
return FALSE;
return TRUE;
}
// 设置会话名称
BOOL set_session_name(char * name)
{
DPSESSIONDESC2 dpsd;
DWORD size = 0;
lpDP->GetSessionDesc(&dpsd, &size);
dpsd.lpszSessionNameA = name;
if (FAILED(lpDP->SetSessionDesc(&dpsd, 0)))
return FALSE;
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -