#include #include #include #include #include #include #include #include #include #include #include #include using namespace std; class Room { public: string name; int desc; Room(int d, string n) { desc = d; name = n; } }; class Client { public: int desc; string Name; vector rooms; Client(int d, string n) { desc = d; Name = n; } }; string join = "/join"; set rooms; vector clients; set meta; set list; int metadata = -2; int port; int t; // Czy main room int i, j; int fdmax = -1; //najwiekszy deskryptor int listener; //nasluchujacy dekspytor int newfd; //najnowszy zaakceptowany int nbytes; int guest = 0; int yes = 1; fd_set master; fd_set read_fds; fd_set write_fds; struct sockaddr_in serveraddr; struct sockaddr_in serveraddr_meta; struct sockaddr_in clientaddr; socklen_t addrlen; const string delimeterMetaDate = "@@DONE\n"; vector msg_split; string tt; int iterator = 0; int unexpected_error = 0; string message; char bufor[256]; size_t fnd; int size; void createSocket() { if ((listener = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("Server-socket()-listener error"); exit(1); } printf("Server-socket()-listener is OK...\n"); } void createSetSockopt() { if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { perror("Server-setsockopt()-listener error"); exit(1); } printf("Server-setsockopt()-listener is OK...\n"); } void SetListener() { serveraddr.sin_family = AF_INET; serveraddr.sin_addr.s_addr = INADDR_ANY; serveraddr.sin_port = htons(port); if (bind(listener, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) == -1) { perror("Server-bind()-listener error"); exit(1); } printf("Server-bind()-listener is OK...\n"); if (listen(listener, 5) == -1) //kolejka { perror("Server-listen()-listener error"); exit(1); } printf("Server-listen()-listener is OK...\n"); } void CreateMetaData() { if ((metadata = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("Server-socket()-metadata error"); exit(1); } printf("Server-socket()-metadata is OK...\n"); if (setsockopt(metadata, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { perror("Server-setsockopt()-metadata error"); exit(1); } printf("Server-setsockopt()-metadata is OK...\n"); serveraddr_meta.sin_family = AF_INET; serveraddr_meta.sin_addr.s_addr = INADDR_ANY; serveraddr_meta.sin_port = htons(port - 1); if (bind(metadata, (struct sockaddr*)&serveraddr_meta, sizeof(serveraddr_meta)) == -1) { perror("Server-bind()-meta error"); exit(1); } printf("Server-bind()-meta is OK...\n"); if (listen(metadata, 5) == -1) //kolejka { perror("Server-listen()-metadata error"); exit(1); } printf("Server-listen()-metadata is OK...\n"); } bool isMessageAddRoom(string message) { return message.find(join) != std::string::npos; } void sendMessage(int m,string avamys) { int sent = 0; unsigned int got = 0; do { sent = send(m, avamys.c_str() + got, avamys.size() - got, MSG_CONFIRM); got += sent; } while (got < avamys.size()); } void sendMetadata(){ for (int m: meta){ if (m != metadata){ for (Client *c : clients){ for (Room r : c->rooms){ string row = to_string(r.desc) + ":" + r.name + ":" + c->Name; row.append("\n"); sendMessage(m,row); } } sendMessage(m,delimeterMetaDate); } } } void split(const string& s, char delim, vector& elems) { stringstream ss; ss.str(s); string item; while (getline(ss, item, delim)) { elems.push_back(item); } } vector split(const string& s, char delim) { vector elems; split(s, delim, elems); return elems; } void CreateRoom(string text) { port++; vector words_in_message = split(text, ' '); cout<<"nazwa pokoju" << words_in_message[1] << "|"<desc == i) c->rooms.push_back(ro); if (fork()==0){ sendMetadata(); exit(0); } return; } } void ReadMessage() { do{ if((size = read(i, &bufor, 256)) <=0){ if(size == 0){// Jeśli 0 to klient się rozłączył printf("%s: socket %d hung up\n", tt.c_str(), i); //zamkniete } else{// Jeśli 0 to klient się rozłączył perror("recv() error(odbieranie)"); } close(i); //zamykamy i usuwamy z seta FD_CLR(i, &master); list.erase(i); unexpected_error = 1; break; } //Jeśli znaleziono znak końca wiadomości to break i koniec czytania wiadomości string wczytane(bufor); fnd = wczytane.find_first_of("^");//fnd reprezentuje pozycję znaku w stringu if(fnd != string::npos){// Jeśli nie znajdzie znaku w stringu przyjmuje wartość nops czyli wiadmość się nie skończyła if (fnd == 0) break; wczytane = wczytane.substr(0,fnd); message.append(wczytane); break; } message.append(wczytane); }while(fnd == string::npos);// Czytaj dopóki nie wytąpi znak końca } void GetMessage() { cout<< message<desc == i && c->Name.find("Guest") >= 0) { c->Name = msg_split[0]; if (fork()==0) { sendMetadata(); exit(0); } } } } void NewConnect() { addrlen = sizeof(clientaddr); if ((newfd = accept(listener, (struct sockaddr*)&clientaddr, &addrlen)) == -1) { perror("Server-accept()-listener error"); } else { printf("Server-accept()-listener is OK...\n"); FD_SET(newfd, &master); /* add to master set */ list.insert(newfd); Client *temp = new Client(newfd, "Guest"+to_string(guest)); Room ro(port, "Main"); temp->rooms.push_back(ro); clients.push_back(temp); guest++; if (newfd > fdmax) fdmax = newfd; printf("%s: New connection from %s on socket %d\n", tt.c_str() , inet_ntoa(clientaddr.sin_addr), newfd); } } void NewConnectMetaData() { addrlen = sizeof(clientaddr); if ((newfd = accept(metadata, (struct sockaddr*)&clientaddr, &addrlen)) == -1) { perror("Server-accept()-metadata error"); } else { printf("Server-accept()-metadata is OK...\n"); meta.insert(newfd); } if (newfd > fdmax) fdmax = newfd; printf("%s: New connection from %s on socket %d\n", tt.c_str(), inet_ntoa(clientaddr.sin_addr), newfd); } int main(int argc, char* argv[]) { if (argc < 2) { cout << "Nie podano portu!" << endl; return -1; } tt = argv[0]; port = stoi(argv[1]); rooms.insert(tt); t = tt.find("select"); FD_ZERO(&master); FD_ZERO(&read_fds); createSocket(); createSetSockopt(); //set server addr SetListener(); ///////////METADATA////////////////// if (t >= 0) //czy Main room? { CreateMetaData(); } /* listener do mastera */ FD_SET(listener, &master); FD_SET(metadata, &master); if (listener > fdmax) fdmax = listener; if (metadata > fdmax) fdmax = metadata; meta.insert(metadata); list.insert(listener); for (;;){ read_fds = master; if (select(fdmax + 1, &read_fds, NULL, NULL, NULL) == -1) { perror("Server-select() error"); exit(1); } printf("Server-select() is OK...\n"); /*szuka po deskryptorach czy cos do czytania*/ for (i = 0; i <= fdmax; i++) { if (FD_ISSET(i, &read_fds)) { if (i == listener) { NewConnect(); } else if (i == metadata) { NewConnectMetaData(); } else { message = ""; //czytanie ReadMessage(); //update GetMessage(); if(isMessageAddRoom(msg_split[1])) { CreateRoom(msg_split[1]); } cout << "Send message: " << message << endl; /*wysyłanie danych*/ for (j = 0; j <= fdmax; j++) { if (FD_ISSET(j, &master) && list.find(j) != list.end()) { if (j != listener) sendMessage(j,message); } //if } //for } //else } //if (inset) } //for (descs) } //for (;;) return 1; } //main