2017-04-01 3 views
0

Ich bin völlig neu in der Socket-Programmierung.Ich versuche zu verstehen, die verschiedenen Praktiken, wenn es um Socket-Programmierung und die Handhabung mehrerer Verbindungen. Ich habe die folgende Funktionalität also für erreicht.Handle einzelnen Server und mehrere Clients in C++

  • Server an mehrere Clients verbinden. c1, c2, c3 ...... cn.

  • Server sendet ein Zeitfenster zum Client.

  • Server zum Übertragen Nachricht an dem Client senden. (Übertragen
    Nachricht in begrenzten Dauer)

  • Client-Nachricht innerhalb eines begrenzten Zeitperiode senden

  • einmal ersten verbundene Client ist Zeit über Server senden Nachricht an nächste Client für die Übertragung von Nachrichten und so.

Hier ist mein Arbeitscode.

Server.cpp

#include "stdafx.h" 
    #pragma comment(lib,"ws2_32.lib") 
    #include <WinSock2.h> 
    #include <string> 
    #include <iostream> 
    #include<conio.h> 

    #define DEFAULT_NC_TIME 20 
    #define MAX_CLIENTS 2 
    SOCKET Connections[MAX_CLIENTS]; 
    int TotalConnections = 0; 

    #include <vector> 
    #include<time.h> 


void wait (int seconds) 
{ 
    clock_t endwait; 
    endwait = clock() + seconds * CLOCKS_PER_SEC ; 
    while (clock() < endwait) {} 
} 

void ClientHandlerThread(int index) //index = the index in the SOCKET Connections array 
    { 
    int bufferlength; //Holds the length of the message a client sent 
    while (true) 
    { 
     recv(Connections[index], (char*)&bufferlength, sizeof(int), NULL); //get buffer length 
     char * buffer = new char[bufferlength+1]; //Allocate buffer 
     buffer[bufferlength] = '\0'; 
     recv(Connections[index], buffer, bufferlength, NULL); //get buffer message from client 
     std::cout << buffer << std::endl; 
     delete[] buffer; 
    } 
    } 

void emitMessageToClient(int indexOfClient, int ts){ 
     std::string buftest="You are ready to transmit Message.\n"; 
     int size = buftest.size(); //Get size of message in bytes and store it in int size 
     send(Connections[indexOfClient], (char*)&ts, sizeof(int), NULL); //send Timeslot Duration to the client i 
     send(Connections[indexOfClient], (char*)&size, sizeof(int), NULL); //send Size of message 
     send(Connections[indexOfClient], buftest.c_str(), buftest.size(), NULL); //send Message 
     } 


int main() 
    { 
    //Winsock Startup 
    WSAData wsaData; 
    WORD DllVersion = MAKEWORD(2, 1); 
    if (WSAStartup(DllVersion, &wsaData) != 0) 
    { 
     MessageBoxA(NULL, "WinSock startup failed", "Error", MB_OK | MB_ICONERROR); 
     return 0; 
    } 

    SOCKADDR_IN addr; 
    int addrlen = sizeof(addr); 
    addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 
    addr.sin_port = htons(1111); 
    addr.sin_family = AF_INET; 

    SOCKET sListen = socket(AF_INET, SOCK_STREAM, NULL); 
    bind(sListen, (SOCKADDR*)&addr, sizeof(addr)); 
    listen(sListen, SOMAXCONN); 

    SOCKET newConnection; //Socket to hold the client's connection 
    int ConnectionCounter = 0; //# of client connections 
    for (int i = 0; i < MAX_CLIENTS; i++) 
    { 

     newConnection = accept(sListen, (SOCKADDR*)&addr, &addrlen); 
     if (newConnection == 0) 
     { 
      std::cout << "Failed to accept the client's connection." << std::endl; 
     } 
     else 
     { 
      std::cout << "Client "<<i<<" Connected!" << std::endl; 
      Connections[i] = newConnection; 
      TotalConnections += 1; //Increment total # of clients that have connected 
     } 
    } 

    int ts = DEFAULT_NC_TIME/(TotalConnections + 1); // caculating time slot for each of connected node including server 
    std::cout<<"\nPress any key to start transmission: "; 
    getche(); 
    for(int i= 0; i < TotalConnections; i++){ 

     emitMessageToClient(i, ts); 
     CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ClientHandlerThread, (LPVOID)(i), NULL, NULL); 
     wait(ts); 
     if(i == (TotalConnections - 1)){ 
      i = 0; 
     } 
    } 
    system("pause"); 
    return 0; 
} 

Client.cpp

 #include "stdafx.h" 
    #pragma comment(lib,"ws2_32.lib") //Required for WinSock 
    #include <WinSock2.h> //For win sockets 
    #include <string> //For std::string 
    #include <iostream> //For std::cout, std::endl, std::cin.getline 
    #include <time.h> 
    #include <vector> 
    #include <conio.h> 
    SOCKET Connection;//This client's connection to the server 

    void wait (int seconds) 
    { 
     clock_t endwait; 
     endwait = clock() + seconds * CLOCKS_PER_SEC ; 
     while (clock() < endwait) {} 
    } 

    void ClientThread() 
    { 
     int bufferlength; //Holds the length of the message we are receiving 
     int ts; // holds timeslot duration for this client 
     while (true) 
     { 
      recv(Connection, (char*)&ts, sizeof(int), NULL); //receive timeslot 
      recv(Connection, (char*)&bufferlength, sizeof(int), NULL); //receive bufferlength 
      char * buffer = new char[bufferlength+1]; 
      buffer[bufferlength] = '\0'; 
      recv(Connection, buffer, bufferlength, NULL); 
      std::cout << buffer << std::endl; //print out buffer 
      std::string userinput; //holds the user's chat message 

      for (int n= ts; n>0; n--) 
      { 
      userinput = "First client sending message..."; 
      int bufferlength = userinput.size(); //Find buffer length 
      send(Connection, (char*)&bufferlength, sizeof(int), NULL); //Send length of buffer 
      send(Connection, userinput.c_str(), bufferlength, NULL); //Send buffer 
      wait (1); 
      } 
      delete[] buffer; //Deallocate buffer 
     } 
    } 

    int main() 
    { 
     //Winsock Startup 
     WSAData wsaData; 
     WORD DllVersion = MAKEWORD(2, 1); 
     if (WSAStartup(DllVersion, &wsaData) != 0) 
     { 
      MessageBoxA(NULL, "Winsock startup failed", "Error", MB_OK | MB_ICONERROR); 
      return 0; 
     } 

     SOCKADDR_IN addr; 
     int sizeofaddr = sizeof(addr); 
     addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 
     addr.sin_port = htons(1111); 
     addr.sin_family = AF_INET; 

     Connection = socket(AF_INET, SOCK_STREAM, NULL); 
     if (connect(Connection, (SOCKADDR*)&addr, sizeofaddr) != 0) 
     { 
      MessageBoxA(NULL, "Failed to Connect", "Error", MB_OK | MB_ICONERROR); 
      return 0; //Failed to Connect 
     } 

     std::cout << "Connected!" << std::endl; 
     CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ClientThread, NULL, NULL, NULL); 

     getche(); 
     return 0; 
    } 

einmal Server senden Nachricht an alle seine angeschlossenen clients.Server will Nachricht senden wieder zu seinem Erste Client Nachricht erneut senden (zyklisch)

Problem

Wie kann ich, wenn Server reden alle seine Kunden c1, c2, c3 bis Cn erreichen und wieder zu seinem ersten Client C1 sprechen. (Zyklisch) die ich verwendet habe dieses Kontroll

if(i == (TotalConnections - 1)){ 
     i = 0; 
} 

aber das Programm zum Absturz bringen.

+0

Versuchen Sie es mit 'threads' – daemon7osh

+0

Verwenden Sie ein Thread-Pool mit einer Jobwarteschlange. –

+0

@ daemon7osh Der obige Code funktioniert gut. wenn ich es benutze, überprüfe es, crash das Programm.Ich denke auf der Client-Seite CreateThread-Funktion nicht effizient behandeln – Ali

Antwort

0

Wenn Sie i zurück auf 0 setzen, erstellen Sie eine Endlosschleife, da i niemals groß genug für die Schleife wird.

for(int i= 0; i < TotalConnections; i++) { 

    emitMessageToClient(i, ts); 
    CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ClientHandlerThread, (LPVOID)(i), NULL, NULL); 
    wait(ts); 

    // This will create an infinite loop 
    if(i == (TotalConnections - 1)) 
    { 
     i = 0; 
    } 
} 

Was Sie tun können, ist warten, bis die Schleife die erste Verbindung wieder besuchen beendet hat:

for(int i= 0; i < TotalConnections; i++) { 

    emitMessageToClient(i, ts); 
    CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ClientHandlerThread, (LPVOID)(i), NULL, NULL); 
    wait(ts); 
} 

// now the loop is over, revisit the first connection 
// if it exists  
if(TotalConnections > 0) { 

    emitMessageToClient(0, ts); 
    CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ClientHandlerThread, (LPVOID)(0), NULL, NULL); 
    wait(ts); 
} 
+0

Klingt mir wie das OP * * eine Endlosschleife will. Ich denke nicht, dass das das Problem ist. –

Verwandte Themen