Hi,
Ich bin gerade dabei ein hauptsächlich technisch als spielerisch interessantes Projekt zu überarbeiten, welches aus Server und Client besteht, die über ein Netzwerk (UDP-Protokoll) kommunizieren. Da ich bis jetzt auf freie cross-platform Bibliotheken aufgebaut habe, benutze ich in diesem Projekt als Netzwerkbibliothek SDL_net. Im Zuge der Überarbeitung möchte ich eine Servererkennung für den Clienten im lokalen Netzwerk einfügen. Also las ich einige Beispiele für UDP Broadcasting und habe mich für folgende Methode entschieden:
- Der Client broadcasted ein Gesuch ins Netzwerk, dass sich alle Server bitte bei ihm melden sollen (mithilfe der im Paket beigefügten IP)
- Der Server stellt ein Paket zusammen mit seiner eigenen IP, einem Servernamen (z.B.: "Helco's Server") und einer Versionsnummer, um inkompatible Versionen während der Entwicklung voneinander zu trennen und schickt das ganze an den Client
- Dieser kann die Serverinformationen dann dem User anzeigen
Mehr ist im Augenblick für eine Testapplikation nicht nötig sodass ich erst einmal dies getrennt vom eigentlich Projekt austesten wollte.
SDLNet wird wunderbar initialisiert, das Paket (vom Client) wird ohne Fehlermeldung gesendet, aber keines der beiden Programme empfängt je irgendein Paket, selbst als ich das Serverprogramm auf einen anderen Computer (im selben Netzwerk) ausgelagert habe.
Erkennt ihr den Fehler?
common.h
|
C-/C++-Quelltext
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
#include <iostream>
#include <string>
#include <sstream>
#include <SDL/SDL.h>
#include <SDL/SDL_net.h>
using namespace std;
#ifdef _MSC_VER
# define PACKED_STRUCT(name) __pragma(pack(push, 1)) struct name __pragma(pack(pop))
#elif defined(__GNUC__)
# define PACKED_STRUCT(name) struct __attribute__((packed)) name
#endif
#define uint unsigned int
#define ushort unsigned short
#define byte unsigned char
string IPtoStr (unsigned int ip)
{
unsigned char* it=(unsigned char*)(&ip);
stringstream s;
s << (short)(*it) << ".";it++;
s << (short)(*it) << ".";it++;
s << (short)(*it) << ".";it++;
s << (short)(*it);
return s.str();
}
IPaddress GetLocalBroadcastIP (unsigned short port)
{
IPaddress ip;
ip.host=0;
ip.port=port;
string hostname=SDLNet_ResolveIP(&ip);
if (hostname=="") {
ip.host=INADDR_NONE;
return ip;
}
SDLNet_ResolveHost(&ip,hostname.c_str(),25336);
return ip;
}
#define PACKET_HEADER 0x43424f52 //ASCII for "ROBC"
#define ROBCO_VERSION 0x0201 //Ver.: 1.2
enum PacketType
{
PACKET_BROADCAST_QUERY=0,
PACKET_BROADCAST_SIGNAL=1
};
//__pragma(pack(push, 1)) struct name __pragma(pack(pop))
PACKED_STRUCT(PacketHeader
{
uint magic;
byte type;
});
PACKED_STRUCT(PacketBroadcastQuery
{
uint magic;
byte type;
uint ipHost;
ushort ipPort;
});
PACKED_STRUCT(PacketBroadcastSignal
{
uint magic;
byte type;
uint ipHost;
ushort ipPort;
char name[16];
ushort version;
});
|
server.cpp
|
C-/C++-Quelltext
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
#include <Windows.h>
#include <conio.h>
#include "../common.h"
int main (int argc,char* argv[])
{
string name;
cout << "Server name:";
cin >> name;
if (name.length()>15) {
name=name.substr(0,15);
cout << "Warning! Name is too long and will be reduced to \"" << name<< "\"!" << endl;
}
if (SDLNet_Init ()<0) {
cout << SDLNet_GetError () << endl;
system("pause");
return -1;
}
IPaddress myIP=GetLocalBroadcastIP (25336);
UDPsocket socket=SDLNet_UDP_Open (25336);
UDPpacket* packet=SDLNet_AllocPacket (1024);
PacketHeader* header;
PacketBroadcastQuery* broadcastQuery;
PacketBroadcastSignal* broadcastSignal;
cout << "IP:" << IPtoStr(myIP.host) << endl;
while (!_kbhit()) {
if (SDLNet_UDP_Recv(socket,packet)) {
header=(PacketHeader*)packet->data;
if (packet->len<6||header->magic!=PACKET_HEADER)
continue;
if (header->type==PACKET_BROADCAST_QUERY) {
if (packet->len!=sizeof(PacketBroadcastQuery))
cout << "Received invalid broadcast query packet!" << endl;
else {
broadcastQuery=(PacketBroadcastQuery*)header;
cout << "Received broadcast query from: " << IPtoStr(broadcastQuery->ipHost) << ":" << broadcastQuery->ipPort << endl;
packet->address.host=broadcastQuery->ipHost;
packet->address.port=broadcastQuery->ipPort;
broadcastSignal=(PacketBroadcastSignal*)header;
broadcastSignal->type=PACKET_BROADCAST_SIGNAL;
broadcastSignal->ipHost=myIP.host;
broadcastSignal->ipPort=myIP.port;
memset(broadcastSignal->name,0,16);
memcpy(broadcastSignal->name,&(name[0]),15);
broadcastSignal->version=ROBCO_VERSION;
packet->len=sizeof(PacketBroadcastSignal);
SDLNet_UDP_Send(socket,-1,packet);
}
}
else
cout << "Received invalid packet:" << short(header->type) << endl;
}
Sleep(5);
}
SDLNet_FreePacket(packet);
SDLNet_UDP_Close (socket);
SDLNet_Quit ();
system("pause");
return 0;
}
|
client.cpp
|
C-/C++-Quelltext
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
#include <Windows.h>
#include <conio.h>
#include "../common.h"
int main (int argc,char* argv[])
{
if (SDLNet_Init ()<0) {
cout << SDLNet_GetError () << endl;
system("pause");
return -1;
}
IPaddress myIP=GetLocalBroadcastIP(25336);
//SDLNet_ResolveHost(&myIP,"192.168.100.2",25336);
UDPsocket socket=SDLNet_UDP_Open (25336);
UDPpacket* packet=SDLNet_AllocPacket(1024);
PacketBroadcastQuery* query;
PacketBroadcastSignal* signal;
PacketHeader* header;
query=(PacketBroadcastQuery*)packet->data;
query->magic=PACKET_HEADER;
query->type=PACKET_BROADCAST_QUERY;
query->ipHost=myIP.host;
query->ipPort=myIP.port;
packet->address.host=INADDR_BROADCAST;
packet->address.port=25336;
packet->len=sizeof(PacketBroadcastQuery);
system("pause");
if (SDLNet_UDP_Send(socket,-1,packet)<0) {
cout << SDLNet_GetError () << endl;
}
cout << "Server name |Version" << endl
<< "----------------+-------" << endl;
int r;
while (!_kbhit()) {
r=SDLNet_UDP_Recv(socket,packet);
if (r<0)
cout << SDLNet_GetError () << endl;
else if (r>0) {
header=(PacketHeader*)packet->data;
if (packet->len<6||header->magic!=PACKET_HEADER)
continue;
if (header->type==PACKET_BROADCAST_SIGNAL) {
if (packet->len<sizeof(PacketBroadcastSignal))
cout << "Received invalid broadcast signal packet!" << endl;
else {
signal=(PacketBroadcastSignal*)header;
string name;
name.resize(16,' ');
memcpy(&(name[0]),signal->name,15);
cout << name << "|" << (signal->version&0xff) << "." << (signal->version>>8) << endl;
}
}
else
cout << "Received invalid packet: " << short(header->type) << endl;
}
Sleep(5);
}
SDLNet_UDP_Close(socket);
SDLNet_FreePacket(packet);
SDLNet_Quit ();
system("pause");
return 0;
}
|