int main(int argc, const char **argv) { try { if (argc != 5) { std::cerr << "Usage: " << argv[0] << " CONNECTION-URL AMQP-ADDRESS MESSAGE-COUNT THREAD-COUNT\n" "CONNECTION-URL: connection address, e.g.'amqp://127.0.0.1'\n" "AMQP-ADDRESS: AMQP node address, e.g. 'examples'\n" "MESSAGE-COUNT: number of messages to send\n" "THREAD-COUNT: number of sender/receiver thread pairs\n"; return 1; } const char *url = argv[1]; const char *address = argv[2]; int n_messages = atoi(argv[3]); int n_threads = atoi(argv[4]); int count = n_messages * n_threads; // Total messages to be received, multiple receiver threads will decrement this. std::atomic_int remaining; remaining.store(count); // Run the proton container proton::container container; auto container_thread = std::thread([&]() { container.run(); }); // A single sender and receiver to be shared by all the threads sender send(container, url, address); receiver recv(container, url, address); // Start receiver threads, then sender threads. // Starting receivers first gives all receivers a chance to compete for messages. std::vector<std::thread> threads; threads.reserve(n_threads*2); // Avoid re-allocation once threads are started for (int i = 0; i < n_threads; ++i) threads.push_back(std::thread([&]() { receive_thread(recv, remaining); })); for (int i = 0; i < n_threads; ++i) threads.push_back(std::thread([&]() { send_thread(send, n_messages); })); // Wait for threads to finish for (auto& t : threads) t.join(); send.close(); recv.close(); container_thread.join(); if (remaining > 0) throw std::runtime_error("not all messages were received"); std::cout << count << " messages sent and received" << std::endl; return 0; } catch (const std::exception& e) { std::cerr << e.what() << std::endl; } return 1; }
/*------------------------------------------------------------------------------------------------------------------ -- FUNCTION: main -- -- DATE: MAR 23 2016 -- -- REVISIONS: MAR 23 2016 - Version 1 -- -- DESIGNER: Spenser Lee -- -- PROGRAMMER: Spenser Lee -- -- INTERFACE: int main(int argc, char const *argv[]) -- argc: number of commandl line arguments -- argv: array of command line arguments -- -- RETURNS: int: success -- -- NOTES: -- The entry point for the client program. This function handles accepts and assigns the command line argument for -- priority. If valid arguments are received, it will attempt to create a message queue, and override default signaling. -- Then it will prompt the user for a filename through standard input, and send a request message to message queue. -- It will then create a thread that waits to file messages from the queue. ----------------------------------------------------------------------------------------------------------------------*/ int main(int argc, char *argv[]) { struct hostent *hp; struct sockaddr_in server; struct sockaddr_in local_addr; string host; string username; string message; string address; char ip[16]; char **pptr; int port; if (!proccess_args(&argc, argv, &host, &port, &username, &logactive)) { exit(EXIT_FAILURE); } if (logactive) { myfile.open ("log.txt",ios::trunc); myfile.close(); myfile.open ("log.txt",ios::app); } signal(SIGINT, signal_handler); if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { cerr << "Failed to create socket" << endl; exit(EXIT_FAILURE); } memset (&server, 0, sizeof(server)); server.sin_family = AF_INET; server.sin_port = htons(port); if ((hp = gethostbyname(host.c_str())) == NULL) { cerr << "Unknown server address" << endl; exit(EXIT_FAILURE); } memcpy((char *) &server.sin_addr, hp->h_addr, hp->h_length); if (connect (sd, (struct sockaddr *)&server, sizeof(server)) == -1) { cerr << "Couldn't connect to server" << endl; exit(EXIT_FAILURE); } pptr = hp->h_addr_list; cout << "Connected: " << hp->h_name << " " << inet_ntop(hp->h_addrtype, *pptr, ip, sizeof(ip)) << endl; thread receive_thread(receive_message); socklen_t addr_len = sizeof(local_addr); getsockname(sd, (struct sockaddr*)&local_addr, &addr_len); address = inet_ntoa( local_addr.sin_addr); while (1) { getline(cin, message); if (username.empty()) { message = "[" + get_time() + "] " + address + ": " + message; } else { message = "[" + get_time() + "] " + address + " (" + username + "): " + message; } if (message.length() <= BUFLEN) { send (sd, message.c_str(), BUFLEN, 0); if(logactive){ myfile<<message.c_str()<<endl; } } else { cout << "Error: message too long" << endl; } } }