Socket Server / Client
-
Moin!
In den Programmen soll man mit der Client Seite Nachrichten an die anderen Clienten schicken (Chatprogramm).
Kann man den Clienten so verändern, dass die Eingabe für die zu schickene NAchricht parallel zum Empfang neuer Nachrichten ist? (Stichpunkt: C++ 11 / 14 Thread, etc?).
Und wenn ja, gibt es in der Richtung keine Probleme mit dem Socket? (Verklemmung, etc)
Danke
Server:
//#pragma comment( lib,"ws2_32.lib" ) #include <windows.h> #include <winsock2.h> // bei manchan compilern muss man nur windows.h includieren (zB VC++) #include <stdio.h> #define MAX_CLIENTS 10 int startWinsock(void) { WSADATA wsa; return WSAStartup(MAKEWORD(2,0),&wsa); } int main() { long rc; SOCKET acceptSocket; //SOCKET connectedSocket; SOCKADDR_IN addr; char buf[256]; char buf2[300]; // zusätzliche Variabeln FD_SET fdSet; SOCKET clients[MAX_CLIENTS]; int i; // Winsock starten rc=startWinsock(); if(rc!=0) { printf("Fehler: startWinsock, fehler code: %ld\n",rc); return 1; } else { printf("Winsock gestartet!\n"); } // Socket erstellen acceptSocket=socket(AF_INET,SOCK_STREAM,0); if(acceptSocket==INVALID_SOCKET) { printf("Fehler: Der Socket konnte nicht erstellt werden, fehler code: %d\n",WSAGetLastError()); return 1; } else { printf("Socket erstellt!\n"); } // Socket binden memset(&addr,0,sizeof(SOCKADDR_IN)); addr.sin_family=AF_INET; addr.sin_port=htons(12345); addr.sin_addr.s_addr=INADDR_ANY; // gewisse compiler brauchen hier ADDR_ANY rc=bind(acceptSocket,(SOCKADDR*)&addr,sizeof(SOCKADDR_IN)); if(rc==SOCKET_ERROR) { printf("Fehler: bind, fehler code: %d\n",WSAGetLastError()); return 1; } else { printf("Socket an port 12345 gebunden\n"); } // In den listen Modus rc=listen(acceptSocket,10); if(rc==SOCKET_ERROR) { printf("Fehler: listen, fehler code: %d\n",WSAGetLastError()); return 1; } else { printf("acceptSocket ist im listen Modus....\n"); } for(i=0;i<MAX_CLIENTS;i++) { clients[i]=INVALID_SOCKET; } while(1) { FD_ZERO(&fdSet); // Inhalt leeren FD_SET(acceptSocket,&fdSet); // Den Socket der verbindungen annimmt hinzufügen // alle gültigen client sockets hinzufügen (nur die die nicht INVALID_SOCKET sind) for(i=0;i<MAX_CLIENTS;i++) { if(clients[i]!=INVALID_SOCKET) { FD_SET(clients[i],&fdSet); } } rc=select(0,&fdSet,NULL,NULL,NULL); // nicht vergessen den ersten parameter bei anderen betriebssystem anzugeben if(rc==SOCKET_ERROR) { printf("Fehler: select, fehler code: %i\n",WSAGetLastError()); return 1; } // acceptSocket is im fd_set? => verbindung annehmen (sofern es platz hat) if(FD_ISSET(acceptSocket,&fdSet)) { // einen freien platz für den neuen client suchen, und die verbingung annehmen for(i=0;i<MAX_CLIENTS;i++) { if(clients[i]==INVALID_SOCKET) { clients[i]=accept(acceptSocket,NULL,NULL); printf("Neuen Client angenommen (%d)\n",i); break; } } } // prüfen wlecher client sockets im fd_set sind for(i=0;i<MAX_CLIENTS;i++) { if(clients[i]==INVALID_SOCKET) { continue; // ungültiger socket, d.h. kein verbunder client an dieser position im array } if(FD_ISSET(clients[i],&fdSet)) { rc=recv(clients[i],buf,256,0); // prüfen ob die verbindung geschlossen wurde oder ein fehler auftrat if(rc==0 || rc==SOCKET_ERROR) { printf("Client %d hat die Verbindung geschlossen\n",i); closesocket(clients[i]); // socket schliessen clients[i]=INVALID_SOCKET; // seinen platz wieder freigeben } else { int j=0; for(j=0;j<MAX_CLIENTS;j++) { if (j==i) continue; // aktueller client? if(clients[j]==INVALID_SOCKET) { continue; // ungültiger socket, d.h. kein verbunder client an dieser position im array } send(clients[j],buf,(int)strlen(buf),0); } //buf[rc]='\0'; // daten ausgeben und eine antwort senden //printf("Client %d hat folgendes gesandt: %s\n",i,buf); // antwort senden //sprintf(buf2,"Du mich auch %s\n",buf); //send(clients[i],buf2,(int)strlen(buf2),0); } } } } }
Client:
#include <windows.h> #include <winsock2.h> #include <stdio.h> //Prototypen int startWinsock(void); long getAddrFromString(char* hostnameOrIp, SOCKADDR_IN* addr); int main(int argc, char** argv) { long rc; SOCKET s; SOCKADDR_IN addr; char buf[256]; if(argc<2) { printf("Usage: sock <hostname oder ip des servers>\n"); return 1; } // Winsock starten rc=startWinsock(); if(rc!=0) { printf("Fehler: startWinsock, fehler code: %ld\n",rc); return 1; } else { printf("Winsock gestartet!\n"); } // Socket erstellen s=socket(AF_INET,SOCK_STREAM,0); if(s==INVALID_SOCKET) { printf("Fehler: Der Socket konnte nicht erstellt werden, fehler code: %d\n",WSAGetLastError()); return 1; } else { printf("Socket erstellt!\n"); } // 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 rc=getAddrFromString(argv[1],&addr); if(rc==SOCKET_ERROR) { printf("IP für %s konnte nicht aufgeloest werden\n", argv[1]); return 1; } else { printf("IP aufgeloest!\n"); } rc=connect(s,(SOCKADDR*)&addr,sizeof(SOCKADDR)); if(rc==SOCKET_ERROR) { printf("Fehler: connect gescheitert, fehler code: %d\n",WSAGetLastError()); return 1; } else { printf("Verbunden mit 127.0.0.1..\n"); } // Daten austauschen while(rc!=SOCKET_ERROR) { printf("\nZeichenfolge eingeben [max 256]: "); gets(buf); send(s,buf,strlen(buf),0); rc=recv(s,buf,256,0); if(rc==0) { printf("Server hat die Verbindung getrennt..\n"); break; } if(rc==SOCKET_ERROR) { printf("Fehler: recv, fehler code: %d\n",WSAGetLastError()); break; } buf[rc]='\0'; printf("\nServer antwortet: %s\n",buf); } closesocket(s); WSACleanup(); return 0; } int startWinsock(void) { WSADATA wsa; return WSAStartup(MAKEWORD(2,0),&wsa); } long getAddrFromString(char* hostnameOrIp, SOCKADDR_IN* addr) { //long rc; unsigned long ip; HOSTENT* he; /* Parameter prüfen */ if(hostnameOrIp==NULL || addr==NULL) { return SOCKET_ERROR; } /* eine IP in hostnameOrIp ? */ ip=inet_addr(hostnameOrIp); /* bei einem fehler liefert inet_addr den Rückgabewert INADDR_NONE */ if(ip!=INADDR_NONE) { addr->sin_addr.s_addr=ip; return 0; } else { /* Hostname in hostnameOrIp auflösen */ he=gethostbyname(hostnameOrIp); if(he==NULL) { return SOCKET_ERROR; } else { /*die 4 Bytes der IP von he nach addr kopieren */ memcpy(&(addr->sin_addr),he->h_addr_list[0],4); } return 0; } }
-
Benutze C++ und (Boost.)Asio. Das ist einfacher.
-
TyRoXx schrieb:
Benutze C++ und (Boost.)Asio. Das ist einfacher.
Danke für diesen Hinweis.
Wie muss ich dann bei Codeblocks 13.12 es einstellen bzw den Compiler konfigurieren, dass ich das in Boost kompilieren kann?
Gibt es gute Tutorials für boost?
Kann mir jemand bei meinem Problem für Winsock helfen?
Danke
-
http://wiki.codeblocks.org/index.php?title=BoostWindowsQuickRef
http://forums.codeblocks.org/index.php?topic=15164.0
http://www.secretmaryo.org/wiki/index.php?title=Compiling_on_Windows_with_MinGW_and_Code::Blocks
http://thomast.intellosys.de/2013/01/boost-your-codeblocks/
-
muß du in WIN Anwendung umschreiben:
http://www.codeproject.com/Articles/14032/Chat-Client-Server
https://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=9818&lngWId=3
Boost Beispiele:
http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/examples/cpp03_examples.html