Sockets: Server.exe stürzt einfach ab.
-
Du erzeugst einen Thread mit CreateThread(...),
und rufst dort deine Server Routinen auf.
Während diese dort im Listen mode sind kann dein GUI Thread die Messages des windows handhaben,...greatz
-
okay ich habe jetzt neu angefangen und mal einen Client erstellt.
Problem: Am Ende müsste eine MessageBox kommen die anzeigt ob man Verbunden ist
oder nicht. Die kommt aber nicht.#include "winsock2.h" ..... #pragma comment(lib, "Ws2_32.lib") int startWinsock(void); ..... BOOL CALLBACK ClientSock(HWND, UINT, WPARAM, LPARAM); ..... LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_COMMAND: break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } BOOL CALLBACK ClientSock(HWND hWnd, UINT message, LPARAM lParam, WPARAM wParam) { SOCKET s; long rc; SOCKADDR_IN addr; switch (message) { case WM_COMMAND: /////START WINSOCK rc=startWinsock(); if(rc!=0) { MessageBox(hWnd, _T("Fehler: startWinsock"), _T("Fehler!"), MB_OK); return 1;} /////Clientsocket erstellen s=socket(AF_INET, SOCK_STREAM, 0); if(s==INVALID_SOCKET) { MessageBox(hWnd, _T("ClientSocket nicht erstellt!"), _T("Fehler!"), MB_OK); return 1;} /////Verbinden memset(&addr,0,sizeof(SOCKADDR_IN)); // zuerst alles auf 0 setzten addr.sin_family=AF_INET; addr.sin_port=htons(12345); // wir verwenden mal port 12345 addr.sin_addr.s_addr=inet_addr("127.0.0.1"); // zielrechner ist unser eigener rc=connect(s,(SOCKADDR*)&addr,sizeof(SOCKADDR)); if(rc==SOCKET_ERROR) { MessageBox(hWnd, _T("Verbinden gescheitert!"), _T("Fehler!"), MB_OK); return 1;} else { MessageBox(hWnd, _T("Verbunden!"), _T("Status"), MB_OK);} break; } return 0; } int startWinsock(void) { WSADATA wsa; return WSAStartup(MAKEWORD(2,0),&wsa); }
-
Ich habs mal auf diese Art hier gelöst.
Ist aber nur nen ungefähres Beispiel, wie du es in die Threads einbauen solltest.
Mußt wahrscheinlich noch ein wenig rumknobeln, damit es bei dir zum Laufen kommt.
Das Problem war immer, wenn ich es in WinMain unterbrachte, dann wurde die MessageBearbeitung blockiert, und das Fenster blieb hängen.
(So wie bei dir auch)
Also lagerte ich das Listen zunächst in einen eigenen Thread aus.
Dort wird dann auf ein Connect gewartet, die Hauptanwendung kann aber weiterhin ihre Messages abarbeiten.
Kommt ein Connect zustande, dann startet der ListenThread einen ConnectThread, der die Kommunikation zwischen Server/Client durchführt.
Ist alles vollbracht, und der Client loggt sich aus, dann wird auch der Connect Thread beendet und der ListenThread kann wieder gestartet werden.
Denkbar ist hier auch, dass der Listen Thread MultiSocket-fähig gemacht wird, so daß er mehrere ConnectThread starten kann.
Aber das müßtest du dir selbst austüfteln. (Dafür muss dem ConnectThread der Socket übergeben werden)Die grundlegende Technik ist diese:
WinMain startet Listen Thread.
WinMain arbeitet weiterhin Messages ab. (Kann auch welche vom ListenThread empfangen oder auch späer vom ConnectThread)
ListenThread wartet auf Verbindungen.
Verbindung trifft ein, es wird ein ConnectThread gestartet.
ListenThread kann weitere ConnectThreads starten wenn weitere Verbindugen angefragt werden.
ConnectThread bearbeitet den Datenaustauch Server/Client.
ConnectThread wird nach Abschluß beendet.So im Groben.
DWORD WINAPI Listen(LPVOID); DWORD WINAPI Connect(LPVOID); WinMain() { In WinMain rufst du dann CreateThread(NULL,0,Listen,(LPVOID)0,0,0); auf. } // Habe mal deinen ListenCode hier eingestellt, weiß nit, ob der auch wirklich läuft. DWORD WINAPI Listen(LPVOID) { SOCKET s; long rc; SOCKADDR_IN addr; /////START WINSOCK rc=startWinsock(); if(rc!=0) { MessageBox(hWnd, _T("Fehler: startWinsock"), _T("Fehler!"), MB_OK); return 1;} /////Clientsocket erstellen s=socket(AF_INET, SOCK_STREAM, 0); if(s==INVALID_SOCKET) { MessageBox(hWnd, _T("ClientSocket nicht erstellt!"), _T("Fehler!"), MB_OK); return 1;} /////Verbinden memset(&addr,0,sizeof(SOCKADDR_IN)); // zuerst alles auf 0 setzten addr.sin_family=AF_INET; addr.sin_port=htons(12345); // wir verwenden mal port 12345 addr.sin_addr.s_addr=inet_addr("127.0.0.1"); // zielrechner ist unser eigener rc=connect(s,(SOCKADDR*)&addr,sizeof(SOCKADDR)); if(rc==SOCKET_ERROR) { MessageBox(hWnd, _T("Verbinden gescheitert!"), _T("Fehler!"), MB_OK); return 1;} else { MessageBox(hWnd, _T("Verbunden!"), _T("Status"), MB_OK); CreateThread(NULL, 0, Connect, (LPVOID)0, 0, 0);} } DWORD WINAPI Connect(LPVOID) { Hier die Server/Client Kommunikation, Datentransfer usw. unterbringen, ebenso, das Beenden der Verbindung und Aufräumen. }Wie gesagt, mußt da noch ein wenig rumbasteln.
Gruß,
DC
-
alles kla. versuch ich morgen
-
was muss ich denn hinschreiben stadt hWnd? z.b bei ner message box?
-
Da du ja nur ein Fenster verwendest, und zwar das der Hauptanwendung musst du natürlich auch dessen hwnd benutzen.
Man kann aber auch NULL eintragen, klappt auch.MessageBox(NULL, _T("Verbinden gescheitert!"), _T("Fehler!"), MB_OK);Gruß,
DC
-
irgentwas stimmt nicht
DWORD WINAPI Listen(LPVOID) { SOCKET s; long rc; SOCKADDR_IN addr; /////START WINSOCK rc=startWinsock(); if(rc!=0) { MessageBox(NULL, _T("Fehler: startWinsock"), _T("Fehler!"), MB_OK); return 1;} /////Clientsocket erstellen s=socket(AF_INET, SOCK_STREAM, 0); if(s==INVALID_SOCKET) { MessageBox(NULL, _T("ClientSocket nicht erstellt!"), _T("Fehler!"), MB_OK); return 1;} /////Verbinden memset(&addr,0,sizeof(SOCKADDR_IN)); addr.sin_family=AF_INET; addr.sin_port=htons(12345); addr.sin_addr.s_addr=inet_addr("127.0.0.1"); rc=connect(s,(SOCKADDR*)&addr,sizeof(SOCKADDR)); if(rc==SOCKET_ERROR) { MessageBox(NULL, _T("Verbinden gescheitert!"), _T("Fehler!"), MB_OK); return 1;} else { MessageBox(NULL, _T("Verbunden!"), _T("Status"), MB_OK); } int startWinsock(void) { WSADATA wsa; return WSAStartup(MAKEWORD(2,0),&wsa); }1>f:\api_tutorial\clientsocket\clientsocket\clientsocket.cpp(169): error C2601: 'startWinsock': Lokale Funktionsdefinitionen sind unzulässig
1> f:\api_tutorial\clientsocket\clientsocket\clientsocket.cpp(136): Diese Zeile enthält eine '{', die keine Entsprechung hat
1>f:\api_tutorial\clientsocket\clientsocket\clientsocket.cpp(176): fatal error C1075: Dateiende erreicht, bevor das zugehörige Element für das linke Element Klammer "{" in "f:\api_tutorial\clientsocket\clientsocket\clientsocket.cpp(136)" gefunden wurde
-
metapoint2011 schrieb:
1> f:\api_tutorial\clientsocket\clientsocket\clientsocket.cpp(136): Diese Zeile enthält eine '{', die keine Entsprechung hat
Na dann schau doch mal, ob du für jede { auch eine } hast.
-
{ MessageBox(NULL, _T("Verbunden!"), _T("Status"), MB_OK);Hier fehlt die Schließklammer }
Und der andere Fehler zeigt dir an, daß du wohl startWinsock lokal definiert hast.
Vielleicht auch kenen Prototypen am Anfang definiert?Gruß,
DC
-
Don Carsto schrieb:
Und der andere Fehler zeigt dir an, daß du wohl startWinsock lokal definiert hast.
Das ist ein Folgefehler der fehlenden Klammer.
-
hab den definiert. jetzt hab ich die klammer gesetzt und fehler:
"Listen": Nicht alle Steuerelementpfade geben einen Wert zurück.
und es wird nix angezeigt
-
metapoint2011 schrieb:
"Listen": Nicht alle Steuerelementpfade geben einen Wert zurück.
Deine Funktion soll laut Deklaration ein DWORD zurückgeben. Tut sie aber nicht.
metapoint2011 schrieb:
und es wird nix angezeigt
Dann steht das Programm wohl noch im connect.
-
MFK schrieb:
metapoint2011 schrieb:
"Listen": Nicht alle Steuerelementpfade geben einen Wert zurück.
Deine Funktion soll laut Deklaration ein DWORD zurückgeben. Tut sie aber nicht.
und wie mach ich das?
metapoint2011 schrieb:
und es wird nix angezeigt
Dann steht das Programm wohl noch im connect.
oh stimmt ja.
-
metapoint2011 schrieb:
MFK schrieb:
Deine Funktion soll laut Deklaration ein DWORD zurückgeben. Tut sie aber nicht.
und wie mach ich das?
Mit der return-Anweisung.
-
{ MessageBox(NULL, _T("Verbunden!"), _T("Status"), MB_OK);} return 0; }
-
alles klar geht. jetzt mach ich schnell den server.
-
wenn ich jetzt den server starte kommt garnix. und wenn ich dazu den client starte kommt auch nicht
Server:
DWORD WINAPI Listen(LPVOID) { SOCKET s; SOCKET connectedSocket; long rc; SOCKADDR_IN addr; ///// Serversocket erstellen s=socket(AF_INET,SOCK_STREAM,0); /////Server Binden memset(&addr,0,sizeof(SOCKADDR_IN)); addr.sin_family=AF_INET; addr.sin_port=htons(12345); addr.sin_addr.s_addr=ADDR_ANY; rc=bind(s,(SOCKADDR*)&addr,sizeof(SOCKADDR_IN)); if(rc==SOCKET_ERROR) { MessageBox(NULL, _T("Server Binden gescheitert!"), _T("Fehler"), MB_OK); return 1;} /////Server listen rc=listen(s,10); if(rc==SOCKET_ERROR) { MessageBox(NULL, _T("Listen Fehler!"), _T("Fehler"), MB_OK);} else { MessageBox(NULL, _T("Server ist im listenmodus....."), _T("Info"), MB_OK);} /////Eingehende Verbindungen Akzeptieren connectedSocket=accept(s,NULL,NULL); if(connectedSocket==INVALID_SOCKET) { MessageBox(NULL,_T("accept Fehler!"), _T("Fehler"), MB_OK); return 1;} else { MessageBox(NULL, _T("Neue Verbindung Akzeptiert!"), _T("Status"), MB_OK); } return 0; } int startWinsock(void) { WSADATA wsa; return WSAStartup(MAKEWORD(2,0),&wsa); }hab jetzt n button gemacht im hauptfenster. wenn ich ihn klicke gehts
case WM_COMMAND: switch(LOWORD(wParam)) { case 1: CreateThread(NULL,0,Listen,(LPVOID)0,0,0); } break;nur kommt dann server binden gescheitert
-
zeig mal die WinMain.
Wo rufst du denn den ListenThread auf?
-
was auch komisch war, das das auch schon kam als ich den button getrückt habe,
obwohl ich die switch schleife mit wParam noch garnicht geschrieben hatte.LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { static HWND hWndBtn; PAINTSTRUCT ps; HDC hdc; switch (message) { case WM_CREATE: hWndBtn = CreateWindow(_T("button"), _T("start"), WS_VISIBLE | WS_CHILD | WS_BORDER, 10, 10, 40, 21, hWnd, (HMENU) 1, hInst, NULL ); return 0; case WM_COMMAND: switch(LOWORD(wParam)) { case 1: CreateThread(NULL,0,Listen,(LPVOID)0,0,0); break; } return 0; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); ......................
-
Jaja, hattest ja vorher schon gepostet, daß du nun nen Button hast.
Der Thread wird ja nun auch gestartet.
Aber irgendwas stimmt mit dem Bind nicht.
socketAccept = socket(AF_INET, SOCK_STREAM, 0); // Initialisieren der Struktur SOCKADDR_IN memset(&addrBind, 0, sizeof(SOCKADDR_IN)); addrBind.sin_port = htons(12345); addrBind.sin_family = AF_INET; addrBind.sin_addr.s_addr = ADDR_ANY; result=bind(socketAccept, (SOCKADDR*) &addrBind, sizeof(SOCKADDR_IN)); if(result == SOCKET_ERROR) { MessageBox(NULL, _T("Server Binden gescheitert!"), _T("Fehler"), MB_OK); return 1; } else { MessageBox(NULL, _T("Server Binden erfolgreich!"), _T("OK"), MB_OK); }So sieht das Binding bei mir aus.
Mußte mal gucken und mit deinem vergleichen.
Bei mir läuft es so.