Winsockproblem
-
Hi,
nachdem mir ja im anderen Thread niemand mehr antwortet, habe ich mich nun entschlossen, meinen Server erstmal doch nicht multithreaded zu schreiben und am Anfang auch select() statt asynchronen Sockets zu verwenden.
Allerdings schlägt gerade select() bei mir immer fehl...
EDIT: Ich weiß, ist etwas viel Code, aber das meiste ist nur Initialisierung, die hoffentlich richtig ist
Los geht's mit Application::Application() und dann kommt Application::run(), wo der Fehler bei select() auftritt!
class Connection { public: Connection(void); ~Connection(void); }; class Socket { public: Socket(void); ~Socket(void); SOCKET getSocket(void) const { return m_hSocket; } protected: SOCKET m_hSocket; }; class ListenSocket : public Socket { public: ListenSocket(unsigned long lPort); }; class TCPSocket : public Socket { public: TCPSocket(ListenSocket listenSocket); }; class FDSet { public: FDSet(void); void operator<<(Socket socket); void operator>>(Socket socket); bool contains(Socket socket) const; void performSelect(void); //private: FD_SET m_fdSet; }; Connection::Connection(void) { GUARD; WSADATA wsaData; unsigned long lErrorCode = WSAStartup(MAKEWORD(2, 0), &wsaData); if (lErrorCode) GB_THROW("WSAStartup failed with error code + " + fromLong(lErrorCode) + "!") UNGUARD; } Connection::~Connection(void) { WSACleanup(); } Socket::Socket(void) : m_hSocket(0) {} Socket::~Socket(void) { if (m_hSocket) closesocket(m_hSocket); } ListenSocket::ListenSocket(unsigned long lListenPort) { GUARD; if ((m_hSocket = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) GB_THROW("socket() failed with error code " + fromLong(WSAGetLastError()) + "!") else std::cout << "Listening socket created." << std::endl; SOCKADDR_IN sockAddr; memset(&sockAddr, 0, sizeof(sockAddr)); sockAddr.sin_addr.s_addr = INADDR_ANY; sockAddr.sin_family = AF_INET; sockAddr.sin_port = htons(2711); if (bind(m_hSocket, reinterpret_cast<SOCKADDR*>(&sockAddr), sizeof(sockAddr)) == SOCKET_ERROR) GB_THROW("bind() failed with error code " + fromLong(WSAGetLastError()) + "!") else std::cout << "Bound to port " << lListenPort << "." << std::endl; if (listen(m_hSocket, 10) == SOCKET_ERROR) GB_THROW("listen() failed with error code " + fromLong(WSAGetLastError()) + "!") else std::cout << "Listening..." << std::endl; UNGUARD; } FDSet::FDSet() { FD_ZERO(&m_fdSet); } void FDSet::operator<<(Socket socket) { SOCKET tempSocket = socket.getSocket(); void* p = &m_fdSet; FD_SET(tempSocket, p); } bool FDSet::contains(Socket socket) const { SOCKET tempSocket = socket.getSocket(); return (FD_ISSET(tempSocket, &m_fdSet) != 0); } void FDSet::performSelect(void) { if (select(0, &m_fdSet, 0, 0, 0) == SOCKET_ERROR) GB_THROW("select() failed with error code " + fromLong(WSAGetLastError()) + "!"); } Application::Application() : m_pConnection(0) { GUARD; m_pConnection = new Connection(); m_pListenSocket = new ListenSocket(2711); UNGUARD; } void Application::run(void) { GUARD; FDSet fdSet; // <- Achtung, kein FD_SET, sondern ein Klasse von mir! fdSet << *m_pListenSocket; fdSet.performSelect(); if (fdSet.contains(*m_pListenSocket)) { SOCKET s; if ((s = accept(m_pListenSocket->getSocket(), 0, 0)) == INVALID_SOCKET) GB_THROW("accept() failed with error code " + fromLong(WSAGetLastError()) + "!"); std::cout << "User connected!"; } UNGUARD; }
select() schlägt immer mit dem Fehlercode 10038 fehl, was laut MSDN bedeutet, dass einer der Einträge im FD_SET ungültig, aber wie geht das? (ich weiß, in das FD_SET müssen später noch die Clients rein, aber im Moment wär' ich froh, wenn der Server mal bis zum accept() kommen würde!
ChrisM
-
Hallo,
warum postest du das im C++ Forum? Weder WinSockets noch select sind Standard-C++.
-> WinAPI.
-
Hume war schneller
-
Hi,
lol, natürlich ist select() Standard, wenn man den ersten Parameter unter Unix noch setzt. Ich verwende ja grade Sockets, um das Ganze portabel zu halten.
Wegen dem Code: Sorry, aber ich hab ja grad keine Ahnung, wo der Fehler passiert, aber wahrscheinlich irgendwo in Application::Application() kurz vor dem performSelect()-Aufruf.
Wenn aber niemand der Fehler findet, kommentier ich das Ganze gerne nochmal ausführlich.
ChrisM
-
ChrisM schrieb:
Hi,
lol, natürlich ist select() Standard, wenn man den ersten Parameter unter Unix noch setzt. Ich verwende ja grade Sockets, um das Ganze portabel zu halten.
Humesikkins meint den C++ Standard, und der kennt keine Sockets.
Devil
-
Hi,
achso, dann hat er natürlich recht.
Ich kapier einfach nicht, wo der Fehler liegt. Wenn ich statt der Operator<<-Überladung von FDSet direkt FD_SET verwende, klappt nämlich alles.
Trotzdem steht im Debugger nach beiden Varianten exakt das Gleiche im FD_SET drin.ChrisM
-
aber die operator überladung ist korrekt ?
(Wenn sie es wäre, müsste es doch gehen ;))Devil
-
Hi,
Fehler gefunden: Socket wurde als Value übergeben und so wurde nach der Funktion der Destruktor von Socket aufgerufen und der Socket freigegeben.
Danke trotzdem!
ChrisM