WSAAsyncSelect FD_READ
-
Hallo zusammen,
ich habe folgendes Problem:
Ich habe einen Client der dem Server Pakete schickt. Das Funktioniert auch soweit:
Client
send(client,(char *)&Head, sizeof(Head), 0);Client schickt 4096 bytes.
Der Server Empfänger aber nur 1056 bytes.
Event=WSAGETSELECTEVENT(lParam); switch(Event) { case FD_CLOSE: //MessageBox(NULL, "Geschlossen!", "Connections", MB_ICONEXCLAMATION | MB_OK); break; case FD_READ: memset(&RecvKb,0, sizeof(RecvKb)); memset(&Recv,0,sizeof(Recv)); RecvKb=recv(wParam,(char*)&Recv,RecvSize,0); switch (Recv.PacketType) { case PACKET_USER_CONNECTED: //code ... break;Das heißt es kommen beim ersten Aufruf von FD_READ 1056 bytes und beim zweiten Aufruf kommen 3040 bytes. Somit sind alle 4096 da.
Warum das so ist, ist auch klar. Der interne Buffer war z.B. voll und er hat das in 2 teile gesplittet.Aber wie Manage ich das jetzt? Wie bekommen ich die zwei Teile zu einem und führe dann erst das Kommando PACKET_USER_CONNECTED aus?
Weil es ja auch manchmal so ist, dass beim zweiten Paket die Recv.PacketType nicht drin ist ... und er somit auch nicht PACKET_USER_CONNECTED aufruft. Und wenn es beim ersten mal aufgerufen hat, dann fehlt ja der zweite Teil
Wäre nett wenn mir einer auf die Sprünge helfen könnte.
Vielen Dank
Saiz
-
In dem du einfach wartest bis das komplette Paket (also die 4096 Byte) da ist und du dann erst dein switch-Anweisung ausführst.
-
Ja das ist klar. Aber wie?
Was verschickt ist ... ist ein Struct:
struct PACKETHEAD { DWORD PType; int sendedSize; char Data [4096]; char ID [50]; char ID2 [50]; char ID3 [50]; };Wie binde ich die zwei teile von dem Typ?
-
Du legst dir als Puffer ein Bytearray an, in das du die empfangenen Daten schreibst. Ist das Paket nicht komplett wartest du auf die nächsten Daten und fügst diese deinem Array hinzu. Das machst du so lange bis du ein komplettes Paket hast, welches du dann in deine Struktur übertragen und weiterbearbeiten kannst.
Worauf du achten solltest, ist dass deine Struktur, so wie du sie gepostet hast keine 4096 Byte sondern mindestens 4250 Byte groß ist. Mindestens, weil der Compiler noch Füllbytes (Padding) einfügen kann. Wenn du also die Struktur direkt so verschickst ohne vorher die Daten "von Hand" in in Bytearray zu übertragen kann es dir passieren, dass du sehr schwer zu findende Programmfehler bekommst, wenn du z.B. für Client und Server unterschiedliche Compiler(einstellungen) hast.
-
MMhh tut mir leid ich bin neu in C. Kannst du mir es an einem Beispiel zeigen?
Wie mache ich von der struct ein Bytearray .. und wie wiedr zurück? Wäre sehr dankbar.
Vielen Dank
-
Ungefähr so:
... int willLesen = 4096; int habGelesen = 0; ... switch(...) { ... case FD_READ: int recvResult = recv(..., ((char*) ziel) + habGelesen, willLesen - habGelesen, 0); habGelesen = habGelesen + recvResult; if(habGelesen == willLesen) { Paket ist fertig, weiter wie gehabt und für das nächste Paket habGelesen = 0; ... } else { es muß noch was kommen, deshalb auf das nächste FD_READ warten break; }
-
Vielen Dank!
Es funktioniert super.Eine Frage noch. Ich habe Bild das ich per Socket übertragen will. Momentan mache ich es so .. das ich das Bild abspeichere auf die Festplatte und dann auslese und abschicke.
Wie kann ich das Bild direkt abschicken ohne es erst auf die Festplatte zu schreiben?
So mache ich es momentan:
int GetScreeny(LPWSTR lpszFilename, ULONG uQuality) { ULONG_PTR gdiplusToken; GdiplusStartupInput gdiplusStartupInput; GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); HDC hdcScreen = CreateDC("DISPLAY", NULL, NULL, NULL); HDC hdcCapture = CreateCompatibleDC(hdcScreen); int nWidth = GetDeviceCaps(hdcScreen, HORZRES), nHeight = GetDeviceCaps(hdcScreen, VERTRES), nBPP = GetDeviceCaps(hdcScreen, BITSPIXEL); LPBYTE lpCapture; BITMAPINFO bmiCapture = { { sizeof(BITMAPINFOHEADER), nWidth, -nHeight, 1, nBPP, BI_RGB, 0, 0, 0, 0, 0, } }; HBITMAP hbmCapture = CreateDIBSection(hdcScreen, &bmiCapture, DIB_PAL_COLORS, (LPVOID *)&lpCapture, NULL, 0); if(!hbmCapture){ DeleteDC(hdcCapture); DeleteDC(hdcScreen); GdiplusShutdown(gdiplusToken); return 1; } int nCapture = SaveDC(hdcCapture); SelectObject(hdcCapture, hbmCapture); BitBlt(hdcCapture, 0, 0, nWidth, nHeight, hdcScreen, 0, 0, SRCCOPY); RestoreDC(hdcCapture, nCapture); DeleteDC(hdcCapture); DeleteDC(hdcScreen); CLSID imageCLSID; Bitmap *pScreenShot = new Bitmap(hbmCapture, (HPALETTE)NULL); EncoderParameters encoderParams; encoderParams.Count = 1; encoderParams.Parameter[0].NumberOfValues = 1; encoderParams.Parameter[0].Guid = EncoderQuality; encoderParams.Parameter[0].Type = EncoderParameterValueTypeLong; encoderParams.Parameter[0].Value = &uQuality; GetEncoderClsid(L"image/jpeg", &imageCLSID); int result = (pScreenShot->Save(lpszFilename, &imageCLSID, &encoderParams) == Ok); delete pScreenShot; DeleteObject(hbmCapture); GdiplusShutdown(gdiplusToken); return result; }