2012-03-31 6 views
0

У меня много проблем с отслеживанием, когда я получаю BufferOverrun в коде ниже, когда я отправляю его данные сокета с моего клиента telnet flash/as3. Я в основном стараюсь найти больше утечек памяти и т. Д., Поэтому в дополнение к этой проблеме существует ли более простой способ проверки переполнения или переполнения буфера, чем ручная отладка?Отслеживание буфераOverrun на сервере Socket

/* 
     MTSocketServer 
     -------------- 
     The purpose of this application is to have a client application that can connect to this server. 
     This server should be able to parse messages from connected users and to send them to other users. 
    */ 

    // Headers and Namespace 
    #include "stdafx.h" 
    #include "MTSocketServer.h" 
    using namespace std; 

    // Constants 
    #define BUFFERSIZE 1000 
    #define PORT 20248 

    // Global Variables 
    SOCKET server; 
    struct Client_Data 
    { 
     SOCKET client_socket; 
     string user_id; 
    }; 
    list<Client_Data> clients; 

    // Method Prototypes 
    UINT Server_Thread(LPVOID pParams); 
    UINT Client_Thread(LPVOID pParams); 
    string Recv_String(SOCKET listener); 
    void Send_String(const char* message, SOCKET sender); 
    bool Identity_Exists(string id); 

    int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) 
    { 
     AfxBeginThread(Server_Thread, NULL); 
     while(_getch() != 27); 

     closesocket(server); 
     WSACleanup(); 

     return 0; 
    } 

    UINT Server_Thread(LPVOID pParams) 
    { 
     // Spawn Server Thread 
     cout << "Main thread spawned, press ESC at any time to exit.\r\n"; 
     WSADATA wsa_data; 
     SOCKADDR_IN server_location; 

     if (int wsa_return_val = WSAStartup(0x101, &wsa_data) != 0) 
     { 
      cout << "Incorrect version of 'Ws2_32.dll'.\r\n"; 
      cout << "Client thread de-initialized.\r\n"; 
      AfxEndThread(0, true); 
      return 1; 
     } 

     server_location.sin_family = AF_INET; 
     server_location.sin_addr.s_addr = INADDR_ANY; 
     server_location.sin_port = htons(20248); 

     server = socket(AF_INET, SOCK_STREAM, NULL); 
     if (server == INVALID_SOCKET) 
     { 
      cout << "Socket creation error.\r\n"; 
      cout << "Client thread de-initialized.\r\n"; 
      AfxEndThread(0, true); 
      return 1; 
     } 

     if (bind(server, (SOCKADDR*)&server_location, sizeof(server_location)) != 0) 
     { 
      cout << "Socket binding error.\r\n"; 
      cout << "Client thread de-initialized.\r\n"; 
      AfxEndThread(0, true); 
      return 1; 
     } 

     if (listen(server, 10) != 0) 
     { 
      cout << "Socket listening error.\r\n"; 
      cout << "Client thread de-initialized.\r\n"; 
      AfxEndThread(0, true); 
      return 1; 
     } 

     SOCKET client; 
     SOCKADDR_IN client_location; 
     int len_of_client = sizeof(client_location); 
     bool abort = false; 

     while(abort == false) 
     { 
      client = accept(server, (SOCKADDR*)&client_location, &len_of_client); 

      // Spawn Client Thread 
      cout << "Connection from " << inet_ntoa(client_location.sin_addr) << ". Client thread spawned.\r\n"; 
      AfxBeginThread(Client_Thread, (LPVOID)client); 
     } 

     // De-Initialize Server Thread 
     cout << "Server thread de-initialized.\r\n"; 
     AfxEndThread(0, true); 
     return 0; 
    } 

    UINT Client_Thread(LPVOID pParams) 
    { 
     SOCKET client = (SOCKET)pParams; 
     string client_id = ""; 

     // Check if a client with the same ID is on already 
     send(client, "ID_ME", 6, 0); 
     client_id = Recv_String(client); 

     if (Identity_Exists(client_id)) 
     { 
      Send_String("That ID is already taken. Please try another.", client); 
     } else 
     { 
      cout << "Created ID " << client_id << " successfully\r\n"; 

      Send_String("Type 'send' to send a message, 'quit' to exit.", client); 

      Client_Data this_client; 
      this_client.user_id = client_id; 
      this_client.client_socket = client; 

      clients.push_back(this_client); 

      bool is_con = true; 
      while(is_con) 
      { 
       string response = Recv_String(client); 
       if (response == "send") 
       { 
        Send_String("What username to send to?", client); 
        string to_id = Recv_String(client); 

        if (Identity_Exists(to_id)) 
        { 
         Send_String("Type your message below: ", client); 
         string temp = Recv_String(client) + "\n\0"; 
         const char* message = temp.c_str(); 

         for (list<Client_Data>::iterator iterator = clients.begin(), end = clients.end(); iterator != end; ++iterator) 
         { 
          if (to_id == iterator->user_id) 
          { 
           SOCKET temp = iterator->client_socket; 
           cout << temp; 
           Send_String(message, temp); 
          } 
         } 
        } else 
        { 
         Send_String("Invalid username specified", client); 
        } 
       } 
       else if (response == "quit") 
       { 
        Send_String("Quit Command Issued", client); 
        break; 
       } 
       else 
       { 
        Send_String("Invalid Command Issued", client); 
       } 
      } 
     } 

     // De-Initialize Client Thread 
     closesocket(client); 
     cout << "Client thread de-initialized.\r\n"; 
     AfxEndThread(0, true); 
     return 0; 
    } 

    // Function to parse full string values since they are often recieved one at a time 
    string Recv_String(SOCKET listener) 
    { 
     char buffer[BUFFERSIZE]; 
     string temp; 
     int numofbytes = 0; 

     while (true) 
     { 
      int num = recv(listener, buffer, BUFFERSIZE, 0); 
      numofbytes++; 

      buffer[num] = '\0'; 
      if (buffer[num-1] == '\n') 
       break; 

      if(numofbytes >= BUFFERSIZE-1) 
       break; 

      temp += buffer; 
      strcpy(buffer, ""); 
     } 

     return temp; 
    } 

    void Send_String(const char* message, SOCKET sender) 
    { 
     char buffer[BUFFERSIZE]; 
     strcpy(buffer, message); 
     size_t size = strlen(message); 

     int sendtest = send(sender, buffer, size, 0); 
     strcpy(buffer, ""); 
    } 

    bool Identity_Exists(string id) 
    { 
     for (list<Client_Data>::iterator iterator = clients.begin(), end = clients.end(); iterator != end; ++iterator) 
     { 
      if (id == iterator->user_id) 
      { 
       return true; 
      } 
     } 

     return false; 
    } 

ответ

0

buffer[num] = '\0'; пишет один за буфером, если Num бывает равным BufferSize. Он пишет один ниже буфер, если num имеет значение -1.

if (buffer[num-1] == '\n') хотя и не переполнение буфера, также является неправильным. \ N может быть где угодно (от 0 до n-1) в буфере.

+0

А, я написал это так, так как получал один байт за раз. У вас есть предложение по хорошему способу обработки ввода recv в строку? – winglerw28

+0

Лично я переписал его на C, так как я не делаю C++. По крайней мере, я добавил код управления буфером и удалю все глупые переменные индикатора. – wildplasser

Смежные вопросы