Добрый день всем! Я пытаюсь написать сетевой чат с комнатами, но уже которую неделю не могу понять что не так в моем коде, что некорректно работает переход между комнатами (каждая комната это словарь). Code: /* * server.cpp * * Created on: 22 Nov 2013 * Author: Sergey */ #include <sys/types.h> #include <sys/socket.h> #include <iostream> #include <cstring> #include <sstream> #include <netinet/in.h> #include <map> #include <pthread.h> #include <unistd.h> #include <time.h> using namespace std; int buf_length = 256, nick_length = 16; typedef map <int, const char*, less <int> > room; typedef map <const char*, room*, less <const char*> > room_name_glossary; room_name_glossary rooms; struct connection_info{ int client; room* current_room; }; room* create_room (const char* name); int is_used (char* nick, room& conn); const char* get_nickname (int* handle, room& current_room); int make_info (char* info, const char* nick); void send_to_all (room* current_room, connection_info& con_info, char* buffer, int& result); room* join_room (int& client); int add_connection (int& server); int change_room (connection_info& con_info, room* previous_room); void *new_thread (void *arg); inline room* create_room (const char* name) { room_name_glossary :: iterator i; for (i = rooms.begin(); i != rooms.end(); i++) { if (!(strcmp ((*i).first, name))) return (*i).second; } room* _new_room = new room; rooms [&name [0]] = _new_room; return _new_room; } inline int is_used (char* nick, room& conn) { //Checking if there is such a nickname in the map room :: iterator i; for (i = conn.begin(); i != conn.end(); i++) { if (!(strcmp ((*i).second, nick))) return 1; } return 0; } const char* get_nickname (int* handle, room& current_room) { const char* used_nick_message = "Such a nickname is already being used!\n"; const char* message = "Please, enter your nickname: "; char* nick = new char [nick_length]; int send_result = send (*handle, message, strlen (message), 0); if (send_result == -1) cerr << "Message sending error! (get_nickname)\n"; int recv_result = recv (*handle, &nick [0], nick_length, 0); if (recv_result == -1) { cerr << "Nickname receiving error! (get_nickname)\n"; return "GETTING NICKNAME FAILED"; } while (is_used (nick, current_room)) { send_result = send (*handle, used_nick_message, strlen (used_nick_message), 0); if (send_result == -1) cerr << "Message sending error! (get_nickname)\n"; send_result = send (*handle, message, strlen (message), 0); if (send_result == -1) cerr << "Message sending error! (get_nickname)\n"; memset (nick, 0, nick_length); recv_result = recv (*handle, &nick [0], nick_length, 0); if (recv_result == -1) { cerr << "Nickname receiving error! (get_nickname)\n"; return "GETTING NICKNAME FAILED"; } } return nick; } int make_info (char* info, const char* nick) { //Composes an information about a sender and sending time time_t time_sec = time (0); struct tm* time = localtime (&time_sec); string buffer; stringstream hour, min, sec; hour << time->tm_hour; min << time->tm_min; sec << time->tm_sec; buffer = '[' + hour.str() + ':' + min.str() + ':' + sec.str() + ']' + ' '; buffer.insert(buffer.length(), nick, strlen(nick)); strcpy (info, buffer.c_str()); return 1; } void send_to_all (room* current_room, connection_info& con_info, char* buffer, int& result) { room :: iterator i; char* info_line = new char [buf_length]; for (i = (*current_room).begin(); i != (*current_room).end(); i++) { //Sending messages to all the connections if ((*i).first != con_info.client) { if (!(make_info (info_line, (*current_room) [con_info.client]))) cerr << "Can't compose sender information!"; int send_result = send ((*i).first, info_line, buf_length, 0); if (send_result == -1) cerr << "Nickname sending error! (thread)\n"; send_result = send ((*i).first, &buffer [0], result, 0); if (send_result == -1) { cerr << "Data sending error! (thread)\n"; break; } } } delete [] info_line; } int change_room (connection_info& con_info, room* previous_room) { room_name_glossary :: iterator i; const char* message1 = "None room has been found.\nPlease, enter a name of the new room: "; const char* message2 = "Please, choose one of the existing rooms or create a new one:\n"; if (rooms.empty()) send (con_info.client, message1, strlen (message1), 0); else send (con_info.client, message2, strlen (message2), 0); for (i = rooms.begin(); i != rooms.end(); i++) { //Shows the list of existing rooms send (con_info.client, (*i).first, strlen ((*i).first), 0); } char* received_index = new char [buf_length]; recv (con_info.client, received_index, buf_length, 0); stringstream stream; stream << received_index; int number; stream >> number; i = rooms.begin(); for (int j = 0; j <= number; j++) i++; con_info.current_room = (*i).second; (*con_info.current_room)[con_info.client] = (*previous_room) [con_info.client]; //Rewriting a connection to another room (*previous_room).erase(con_info.client); //Removing a connection from the previous room if (previous_room->empty()) { for (i = rooms.begin(); i != rooms.end(); i++) { if ((*i).second == previous_room) rooms.erase ((*i).first); //Removing a room from the rooms_map } delete previous_room; } return 1; } void *new_thread (void *arg) { connection_info con_info = *(connection_info*)arg; char* buffer = new char [buf_length]; int result; room :: iterator i; do { result = recv (con_info.client, buffer, buf_length, 0); if (result == -1) { cerr << "Data receiving error! (thread)"; break; } room* previous_room = con_info.current_room; //In case a client wants to change a room char* command = buffer; if (!(strcmp (command, "#CHANGE_ROOM\r\n"))) { con_info.current_room = join_room (con_info.client); if (con_info.current_room == previous_room) continue; else { (*con_info.current_room) [con_info.client] = (*previous_room) [con_info.client]; (*previous_room).erase(con_info.client); continue; } } send_to_all (con_info.current_room, con_info, &buffer [0], result); } while (result > 0); delete [] buffer; delete [] (*con_info.current_room) [con_info.client]; if (!((*con_info.current_room).erase(con_info.client))) cerr << "Map element erasing error! (thread)\n"; close (con_info.client); return 0; } room* join_room (int& client) { char* chosen_room_name = new char [buf_length]; room_name_glossary :: iterator i; int result = recv (client, &chosen_room_name [0], buf_length, 0); if (result == -1) { cerr << "Can't receive a room_name!"; return 0; } room* chosen_room = create_room (chosen_room_name); return chosen_room; } int add_connection (int& server) { sockaddr_in client_addr; unsigned int client_addr_len = sizeof (client_addr); while (true) { //Waiting for connections connection_info con_info; con_info.client = accept (server, (sockaddr*) &client_addr, &client_addr_len); if (con_info.client == -1) { cerr << "Accepting error!\n"; continue; } con_info.current_room = join_room (con_info.client); const char* nickname = get_nickname (&con_info.client, *con_info.current_room); if (!(strcmp (nickname, "GETTING NICKNAME FAILED"))) { cerr << "Can't get a nickname, try to connect again!\n"; continue; } (*con_info.current_room) [con_info.client] = nickname; //Adding a new connection pthread_t thread; pthread_create (&thread, 0, &new_thread, (void*) &con_info); //Creating a new thread } close (server); return 0; } int main () { sockaddr_in server_addr; unsigned int server_addr_len = sizeof (server_addr); int server = socket (AF_INET, SOCK_STREAM, 0); server_addr.sin_addr.s_addr = 0; server_addr.sin_family = AF_INET; server_addr.sin_port = htons (1234); int result = bind (server, (sockaddr*) &server_addr, server_addr_len); if (result == -1) { cerr << "Socket binding error!\n"; return 0; } listen (server, SOMAXCONN); add_connection (server); return 0; }