Bei Google wird auch direkt an die Speicherstelle Packet->data geschrieben. Habe mein Problem mit dem Speicherzugriffsfehler gefunden. Ich hatte noch eine Broadcastfunktion (frame(), nun auskommentiert) laufen, welche den Packet->data Zeiger immer auf 0 gesetzt hat. Jetzt kann ich zwar auch Daten in das Paket schreiben, aber empfangen kann ich sie trotzdem nicht. Ich schreib jetzt mal allen netzwerkrelevanten Code zusammen. Vielleicht sieht ja jemand einen Fehler, den ich übersehen habe:
Die gekürzte main.cpp, Client u. Server, haben den gleichen Quelltext, werden durch SERVER-Makro unterschieden:
Code: Alles auswählen
//#define SERVER
//Netzwerkobjekt erstellen
GLNet Netzwerk(&Zeit);
char Daten[1024] = {0};
int Laenge = 6;
int SourceNumber = 0;
bool Server = true;
#ifdef SERVER
//Als Empfängerserver verbinden
Netzwerk.setName("Empfängerserver");
Netzwerk.UDPServer();
#else
//Als Senderclient verbinden
Netzwerk.setName("Senderclient");
Netzwerk.UDPClient();
Netzwerk.ClientToIP(127, 0, 0, 1); //localhost
#endif
while(!Input.getQuit())
{
//Netzwerkframefunktion
//Netzwerk.frame();
#ifdef SERVER
if(Netzwerk.RecvUDP(Daten, Laenge, SourceNumber, Server) && SourceNumber != -1)
{
//Daten konvertieren
std::string Stringtext;
if(Daten[0] == 5)
Stringtext = "Juhu!";
else
Stringtext = "Mist!";
std::string Ausgabe = "Empfangen: ";
Ausgabe += Stringtext;
Output.writel(Ausgabe, 0, 1);
}
#else
//Daten senden
if(Input.isRepeated("enter") && Netzwerk.getState() != "Nicht verbunden/Not connected")
{
char* Text = const_cast<char*> (Eingabe->getText().c_str());
Netzwerk.SendUDP((void*)Text, Eingabe->getText().length());
//Sendebericht ausgeben
std::string Sendingmessage = (std::string)Text;
Sendingmessage += " gesendet an ";
//Anderer Benutzer muss erste Person in Datenbank sein
if(Netzwerk.getState() == "UDPServer")
{
Sendingmessage += Netzwerk.getClientIP(0);
} else {
Sendingmessage += Netzwerk.getServerIP(0);
}
Output.writel(Sendingmessage, 0, 1);
Eingabe->setText("");
}
#endif
}
Die Sende- Empfangsfunktion:
Code: Alles auswählen
void GLNet::SendUDP(void* daten, int laenge)
{
//Wenn keine UDP-Verbindung, abbrechen
if(State == 0 || State == 1 || State == 2) return;
Packet->data[0] = 5;
Packet->len = 1;
//Wenn UDP-Server, an alle Clients senden, sonst an alle Server
if(State == 3 || State == 5 || State == 7)
{
for(int i = 0; i < NumberClients; i++)
{
//IP zuweisen
Packet->address.host = ClientIP[i].host;
Packet->address.port = ClientIP[i].port;
//An eine Adresse (Client) senden
SDLNet_UDP_Send(UDPSocket, -1, Packet);
}
} else {
for(int i = 0; i < NumberServer; i++)
{
//IP zuweisen
Packet->address.host = ServerIP[i].host;
Packet->address.port = ServerIP[i].port;
//An eine Adresse (Server) senden
SDLNet_UDP_Send(UDPSocket, -1, Packet);
}
}
}
bool GLNet::RecvUDP(void* daten, int& maxlaenge, int& number, bool& server) //Liefert true zurück, wenn neue Daten vorhanden (z.B. für Abfrageschleife)
{
//Wenn keine UDP-Verbindung, abbrechen
if(State == 0 || State == 1 || State == 2) return false;
if(SDLNet_UDP_Recv(UDPSocket, Packet) != 1) return false;
daten = (void*)Packet->data;
maxlaenge = Packet->len;
return true;
}
Ich erhalte keinerlei Fehlermeldungen, kann also Daten in das Paket schreiben. Aber die Serverversion meines Programms gibt mir wenn ich ein Paket absende immer "Empfangen: Mist!" aus, also keine "5" auf dem ersten Byte des Pakets.
Die Funktionen zum Verbindungsaufbau, stehen hier nur vorsichtshalber, eine Verbindung erhalte ich ja:
Code: Alles auswählen
void setName(std::string name) {if(State != 0 && State != 3 && State != 4) SendTCPNameChange(name); else Name = name;} //irrelevant, da der Name noch nicht verwendet wird
bool GLNet::UDPServer()
{
//Falls UDPClient, Verbindung beenden
if(State == 4 || State == 6 || State == 8)
EndUDP();
//Nur neu verbinden, wenn noch nicht UDPServer
if(State != 3 && State != 5 && State != 7)
{
UDPSocket = SDLNet_UDP_Open(Port);
//Wenn Socket auf diesem Port nicht erstellen geht, Status anpassen und abbrechen
if(UDPSocket == NULL)
{
//Status passend ändern, da keine UDP-Verbindung mehr und Serververbindung fehlgeschlagen
switch(State)
{
case 4:
//UDPClient -> nicht verbunden
State = 0;
break;
case 6:
//TCPServer/UDPClient -> TCPServer
State = 1;
break;
case 8:
//TCPClient/UDPClient -> TCPClient
State = 2;
break;
}
return false;
}
//Speicher für Paket reservieren
Packet = SDLNet_AllocPacket(Plaenge);
//Status aktualisieren
switch(State)
{
case 0:
//nicht verbunden -> UDPServer
State = 3;
break;
case 1:
//TCPServer -> TCPServer/UDPServer
State = 5;
break;
case 2:
//TCPClient -> TCPClient/UDPServer
State = 7;
break;
case 4:
//UDPClient -> UDPServer
State = 3;
break;
case 6:
//TCPServer/UDPClient -> TCPServer/UDPServer
State = 5;
break;
case 8:
//TCPClient/UDPClient -> TCPClient/UDPServer
State = 7;
break;
}
}
return true;
}
bool GLNet::UDPClient()
{
//Falls UDPServer, Verbindung beenden
if(State == 3 || State == 5 || State == 7)
EndUDP();
//Nur neu verbinden, wenn noch nicht UDPClient
if(State != 4 && State != 6 && State != 8)
{
UDPSocket = SDLNet_UDP_Open(0); //Nächsten freien Port auswählen, sicherer, dass funktioniert (Server erhält Clientports in Paketen)
//Wenn Socket nicht erstellen geht, Status anpassen und abbrechen
if(UDPSocket == NULL)
{
//Status passend ändern, da keine UDP-Verbindung mehr und Clientverbindung fehlgeschlagen
switch(State)
{
case 3:
//UDPServer -> nicht verbunden
State = 0;
break;
case 5:
//TCPServer/UDPServer -> TCPServer
State = 1;
break;
case 7:
//TCPClient/UDPServer -> TCPClient
State = 2;
break;
}
return false;
}
//Speicher für Paket reservieren
Packet = SDLNet_AllocPacket(Plaenge);
//Status aktualisieren
switch(State)
{
case 0:
//nicht verbunden -> UDPClient
State = 4;
break;
case 1:
//TCPServer -> TCPServer/UDPClient
State = 6;
break;
case 2:
//TCPClient -> TCPClient/UDPClient
State = 8;
break;
case 3:
//UDPServer -> UDPClient
State = 4;
break;
case 5:
//TCPServer/UDPServer -> TCPServer/UDPClient
State = 6;
break;
case 7:
//TCPClient/UDPServer -> TCPClient/UDPClient
State = 8;
break;
}
}
return true;
}
bool GLNet::ClientToIP(unsigned char IP1, unsigned char IP2, unsigned char IP3, unsigned char IP4)
{
return add(IP1, IP2, IP3, IP4, true);
}
bool GLNet::add(unsigned char IP1, unsigned char IP2, unsigned char IP3, unsigned char IP4, bool server, std::string userName, int ping, double lastAnswer)
{
//IP konvertieren
Uint32 IP = (IP1 << 24) + (IP2 << 16) + (IP3 << 8) + IP4 ;
unsigned char Puffer[4] = {0};
SDLNet_Write32(IP, Puffer);
IPaddress Adresse;
Adresse.host = (Puffer[3] << 24) + (Puffer[2] << 16) + (Puffer[1] << 8) + Puffer[0];
unsigned char SmallPuffer[2] = {0};
SDLNet_Write16(Port, SmallPuffer);
Adresse.port = (SmallPuffer[1] << 8) + SmallPuffer[0];
//SDLNet_ResolveHost(&Adresse, "localhost", Port); //Nur für Testzwecke
//Schauen ob Server oder Client hinzugefügt wird
if(server)
{
if(NumberServer <= 255)
{
//In Adressdatenbank eintragen
ServerIP[NumberServer] = Adresse;
ServerName[NumberServer] = userName; //Entweder ein Name gesetzt oder ist leer
ServerPing[NumberServer] = ping; //Entweder ein Ping gesetzt oder ist 0
if(lastAnswer != -1) LastServerAnswer[NumberServer] = lastAnswer; else LastServerAnswer[NumberServer] = Time->getGametime();
NumberServer++;
return true;
} else {
return false;
}
} else {
if(NumberClients <= 255)
{
//In Adressdatenbank eintragen
ClientIP[NumberClients] = Adresse;
ClientName[NumberClients] = userName; //Entweder ein Name gesetzt oder ist leer
ClientPing[NumberClients] = ping; //Entweder ein Ping gesetzt oder ist 0
if(lastAnswer != -1) LastClientAnswer[NumberClients] = lastAnswer; else LastClientAnswer[NumberClients] = Time->getGametime();
NumberClients++;
return true;
} else {
return false;
}
}
}
void GLNet::EndUDP()
{
if(UDPSocket) SDLNet_UDP_Close(UDPSocket);
UDPSocket = NULL;
if(Packet) SDLNet_FreePacket(Packet);
Packet = NULL;
//Status aktualisieren
switch(State)
{
case 3:
//UDPServer -> nicht verbunden
State = 0;
break;
case 4:
//UDPClient -> nicht verbunden
State = 0;
break;
case 5:
//TCPServer/UDPServer -> TCPServer
State = 1;
break;
case 6:
//TCPServer/UDPClient -> TCPServer
State = 1;
break;
case 7:
//TCPClient/UDPServer -> TCPClient
State = 2;
break;
case 8:
//TCPClient/UDPClient -> TCPClient
State = 2;
break;
}
}