UDP-Probleme
-
Ich habe außerhalb der MFC eine UDP-Client-Server Anwendung zu Testzwecken geschrieben, bei der der Client eine Broadcast-Nachricht schickt, die dann von allen aktiven Servern zurück geschickt wird.
Das Senden und Empfangen sieht etwa so aus:// Client // Anfrage schicken char request[15] = "Ist jemand da?"; sendto(mSock, request, strlen(request), 0, (SOCKADDR*)&mAddrRequest, sizeof(SOCKADDR_IN)); // mAddrRequest -> Broadcast // Antworten empfangen while(true) { char response[1024]; int responseLen = recvfrom(mSock, response, 1024, 0, (SOCKADDR*)&mAddrResponse, &mAddrResponseLen); // ... }
// Server while(true) { char Request[1024]; int RequestLen = recvfrom(mSock, Request, 1024, 0, (SOCKADDR*)&mAddrResponse, &mAddrResponseLen); Request[RequestLen] = '\0'; // ... sendto(mSock, Request, strlen(Request), 0, (SOCKADDR*)&mAddrResponse, mAddrResponseLen); }
Nun wollte ich den Code in ein MFC-Programm einbinden, die Empfangsschleifen sollten jeweils in einem Arbeitsthread im Hintergund laufen. Nun sind mir im wesentlichen 2 Probleme aufgefallen:
1. recvfrom(...) ist nichtmehr blockierend, d.h. dass z.B. die Serverschleife kontinuierlich durchläuft, auch wenn keine Anfragen von Clients kommen. recvfrom() gibt dabei immer einen Fehler (-1) zurück.
2. Wenn nun eine Anfrage kommt (ob nun von dem MFC-Client oder dem urprünglichen Nicht-MFC-Client) wird diese nicht bearbeitet/beantwortet.Wo liegen möglich/konkrete Fehler? Sockets werden korrekt erstellt/gebunden.
-
Zeig mal etwas Code, wie das Ganze in deiner MFC-Umsetzung aussieht. Zumindest im Server dürfte es problematisch werden, wenn die Empfangsschleife in einem eigenen Thread liegt (bzw. sollte dieser Thread dann auch dafür zuständig sein, die empfangenen Anweisungen auszuwerten).
-
Also der Server:
class CConnectionRequest { private: CWinThread *mThread; bool mStopThread; SOCKET mSock; SOCKADDR_IN mAddrIncoming, mAddrResponse; int mAddrResponseLen; public: CConnectionRequest(); virtual ~CConnectionRequest(); void StartThread(); void StopThread(); static UINT Run(LPVOID pParam); }; CConnectionRequest::CConnectionRequest() { WSADATA wsa; WSAStartup(MAKEWORD(1, 1), &wsa); mSock = socket(AF_INET, SOCK_DGRAM, 0); mAddrIncoming.sin_family = AF_INET; mAddrIncoming.sin_port = htons(6565); mAddrIncoming.sin_addr.s_addr = INADDR_ANY; bind(mSock, (SOCKADDR*)&mAddrIncoming, sizeof(SOCKADDR_IN)); } CConnectionRequest::~CConnectionRequest() { } void CConnectionRequest::StartThread() { StopThread(); mThread = AfxBeginThread(CConnectionRequest::Run, this, THREAD_PRIORITY_BELOW_NORMAL, 0, CREATE_SUSPENDED, NULL); mThread->ResumeThread(); } void CConnectionRequest::StopThread() { mStopThread = true; } UINT CConnectionRequest::Run(LPVOID pParam) { CConnectionRequest *OuterThis = (CConnectionRequest*)pParam; OuterThis->mStopThread = false; while(!OuterThis->mStopThread) { char request[1024]; int requestLen = recvfrom(OuterThis->mSock, request, 1024, 0, (SOCKADDR*)&OuterThis->mAddrResponse, &OuterThis->mAddrResponseLen); request[requestLen] = '\0'; // cout<<Request<<" von "<<inet_ntoa(OuterThis->mAddrResponse.sin_addr)<<endl; if(requestLen>0) { AfxMessageBox(inet_ntoa(OuterThis->mAddrResponse.sin_addr)); sendto(OuterThis->mSock, request, strlen(request), 0, (SOCKADDR*)&OuterThis->mAddrResponse, OuterThis->mAddrResponseLen); } else if(requestLen==-1) AfxMessageBox("Fehler"); } return 0; }
Also im Konstruktor treten keine Fehler auf. Aber die 'Fehlermeldung' aus Zeile 61 kommt ununterbrochen, sobald ich den Thread starte.
-
Also es hat wohl auch nichts damit zu tun, dass es als Thread läuft, den Rufe ich die Methode Run() normal (nicht als Thread) auf, liegt das selbe Problem vor.
-
Der Rückgabewert von recvfrom -1 ist eigentlich ein SOCKET_ERROR und bedeutet nur das ein Fehler aufgetreten ist, um weiter zu spezifizieren, solltest du mit WSAGetLastError() den Fehler abhohlen, dann kann dir warscheinlich jemand weiterhelfen, wenn du dann noch nicht selbst drauf gekommen bist
Gruß Matthias
-
Also WSAGetLastError() gibt mir den Fehlercode 10014 zurück. Leider kann ich damit nicht soviel anfangen. Ich habe nicht mehr als folgendes dazu gefunden:
10014 (WSAEFAULT)
Bei dem Versuch, das Zeigerargument eines Aufrufs zu verwenden, wurde eine ungültige Zeigeradresse gefundenWas soll ich jetzt damit anfangen? Wo liegt der Fehler?
-
OK, ich habe etwas gefunden, ich denke daran lag es:
In Funktion recvfrom() trat er logischerweise auf, und zwar war der Parameter mAddrResponseLen nicht initialisiert. Wenn ich ihn initialisiere, tritt dieser Fehler nichtmehr auf.