Implementiere Benutzerverbindungskontrolle und verbessere Nachrichtenverwaltung
- Füge die Methode `removeUserDisconnected` in der ChatRoom-Klasse hinzu, um Benutzer bei Verbindungsabbrüchen zu entfernen und entsprechende Nachrichten zu senden. - Aktualisiere die ChatUser-Klasse, um einen Token-Getter bereitzustellen und die Verbindungsprüfung zu optimieren. - Ändere die Server-Klasse, um die Benutzerverwaltung bei Raumwechseln zu verbessern und Debug-Informationen hinzuzufügen. - Optimiere die Socket-Optionen für eine schnellere Fehlererkennung und verbessere die Handhabung von Anfragen.
This commit is contained in:
@@ -111,6 +111,11 @@ namespace Yc
|
||||
return _name;
|
||||
}
|
||||
|
||||
std::string ChatUser::getToken() const
|
||||
{
|
||||
return _token;
|
||||
}
|
||||
|
||||
bool ChatUser::validateToken(std::string token)
|
||||
{
|
||||
return (token == _token);
|
||||
@@ -155,16 +160,57 @@ namespace Yc
|
||||
void ChatUser::checkerTask()
|
||||
{
|
||||
try {
|
||||
// Heartbeat-Intervall: Alle 10 Sekunden Verbindung prüfen
|
||||
const int HEARTBEAT_INTERVAL = 2;
|
||||
int heartbeatCounter = 0;
|
||||
|
||||
while (!_stop)
|
||||
{
|
||||
fd_set readSd;
|
||||
FD_ZERO(&readSd);
|
||||
FD_SET(_socket, &readSd);
|
||||
timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 500;
|
||||
int selectResult = select(_socket + 1, &readSd, NULL, NULL, &tv);
|
||||
if (selectResult == 1 && FD_ISSET(_socket, &readSd) == 1)
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
|
||||
// Heartbeat-Check alle 10 Sekunden
|
||||
heartbeatCounter++;
|
||||
if (heartbeatCounter >= HEARTBEAT_INTERVAL) {
|
||||
heartbeatCounter = 0;
|
||||
|
||||
// Prüfe Verbindung mit MSG_PEEK (nicht-blockierend)
|
||||
char peek;
|
||||
ssize_t r = recv(_socket, &peek, 1, MSG_PEEK | MSG_DONTWAIT);
|
||||
|
||||
if (r == 0) {
|
||||
#ifdef YC_DEBUG
|
||||
std::cout << "[Debug] Verbindung zum Client abgebrochen (Token: <hidden>)" << std::endl;
|
||||
#endif
|
||||
_parent->removeUserDisconnected(shared_from_this());
|
||||
_stop = true;
|
||||
if (thread.joinable() && std::this_thread::get_id() == thread.get_id()) {
|
||||
thread.detach();
|
||||
}
|
||||
return;
|
||||
} else if (r < 0) {
|
||||
// EINTR = Interrupted system call (normal), EAGAIN/EWOULDBLOCK = No data available (normal)
|
||||
// Andere Fehler bedeuten Verbindungsabbruch
|
||||
if (errno != EINTR && errno != EAGAIN && errno != EWOULDBLOCK) {
|
||||
#ifdef YC_DEBUG
|
||||
std::cout << "[Debug] Socket-Fehler: " << strerror(errno) << " (Token: <hidden>)" << std::endl;
|
||||
#endif
|
||||
_parent->removeUserDisconnected(shared_from_this());
|
||||
_stop = true;
|
||||
if (thread.joinable() && std::this_thread::get_id() == thread.get_id()) {
|
||||
thread.detach();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Optional: Sende Heartbeat-Ping an Client
|
||||
// (kann helfen, NAT/Firewall-Verbindungen aktiv zu halten)
|
||||
#ifdef YC_DEBUG
|
||||
std::cout << "[Debug] Heartbeat check passed for user: " << _name << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Ursprüngliche Verbindungsprüfung (alle 1 Sekunde)
|
||||
{
|
||||
char peek;
|
||||
ssize_t r = recv(_socket, &peek, 1, MSG_PEEK);
|
||||
@@ -172,7 +218,7 @@ namespace Yc
|
||||
#ifdef YC_DEBUG
|
||||
std::cout << "[Debug] Verbindung zum Client abgebrochen (Token: <hidden>)" << std::endl;
|
||||
#endif
|
||||
_parent->removeUser(_token);
|
||||
_parent->removeUserDisconnected(shared_from_this());
|
||||
_stop = true;
|
||||
if (thread.joinable() && std::this_thread::get_id() == thread.get_id()) {
|
||||
thread.detach();
|
||||
@@ -180,6 +226,7 @@ namespace Yc
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
std::string msg = readSocket(_socket);
|
||||
if (msg == "")
|
||||
{
|
||||
@@ -347,7 +394,7 @@ namespace Yc
|
||||
}
|
||||
else if (jsonTree["type"].asString() == "join")
|
||||
{
|
||||
changeRoom(jsonTree["newroom"].asString(), jsonTree["password"].asString());
|
||||
changeRoom(jsonTree["room"].asString(), jsonTree["password"].asString());
|
||||
}
|
||||
else if (jsonTree["type"].asString() == "userlist")
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user