I've been working on an assignment that asks us to implement some code provided to us that allows the creation of a server and client that can communicate. I was to fork a process in main, and then test the various request options available, and then measure the difference in time it took to do this via the child process, or locally using a function. I'm unsure if I've interpretated the requirements correctly though. On top of this, all the timing functions return 0 seconds. Not sure if this is correct or not. I'll post a small portion of the code.
Homework statement (only a small portion):
Measure the invocation delay of a request (i.e. the time between the
invocation of a request until the response comes back.) Compare that
with the time to submit the same request string to a function that
takes a request and returns a reply (as compared to a separate process
that does the same). Submit a report that compares the two.
The function declared before main:
string myfunc(string request){
//string myreq = request;
RequestChannel my_func_channel("control", RequestChannel::CLIENT_SIDE);
string reply1 = my_func_channel.send_request(request);
return reply1;
}
And how I interpreted the directions in code:
int main(int argc, char * argv[]) {
//time variables
time_t start, end;
double time_req_1, time_req_func;
cout << "client.C Starting...\n" << flush;
cout << "Forking new process...\n " << flush;
pid_t childpid = fork();
if(childpid == -1)
cout << "Failed to fork.\n" << flush;
else if(childpid == 0){
cout << "***Loading Dataserver...\n" << flush;
//Load dataserver
RequestChannel my_channel("control", RequestChannel::CLIENT_SIDE);
cout << "***Dataserver Loaded.\n" << flush;
time(&start);
string reply1 = my_channel.send_request("hello");
cout << "***Reply to request 'hello' is '" << reply1 << "'\n" << flush;
time(&end);
time_req_1 = difftime(end,start);
cout <<"\n\nRequest 1 took : "<< time_req_1 << flush;
}
else{//parent
time(&start);
string s = myfunc("hello");
time(&end);
time_req_func = difftime(end,start);
cout <<"\nmyfunc Request took: "<< time_req_func << "\n" << flush;
}
usleep(1000000);
}
This is an abbreviated version of my code, but contains everything you should need to figure out whats going on. Have I done what the directions stated? Also, is it likely that my 0 seconds results are correct?
The time it takes to do it once may be (probably is) too small to measure, so time how long it takes to do it many times and then work out how long each one took.
Related
for like few hours now, I am trying to figure out how to read characters from cin before pressing ENTER (by using threads). I know about conio.h library but I prefer not to use it.
I wrote simple program that gets data from user and saves it in 'msg' string. Program has child thread that clears the console every second. What I want to do is:
User puts some data but doesn't press ENTER so it's not saved in 'msg' variable.
Console clears
send to cout the characters user typed, so he won't even notice that console was cleared.
PS. Sorry for my english, here's the program:
#include<iostream>
#include<string>
#include<winsock2.h>
#include<process.h>
#include<windows.h>
using namespace std;
void __cdecl ThreadProc( void * Args )
{
while( true ){
system("cls");
cout << "Input: ";
/*
char c;
while((c=cin.peek()) != '\n')
cin.get(c);
cout << c;
*/
Sleep(1000);
}
_endthread();
}
int main(){
HANDLE hThread =( HANDLE ) _beginthread( ThreadProc, 0, NULL );
while (true){
string msg;
getline(cin,msg);
cout << "MSG:" << msg << endl;
cin.clear();
fflush(stdin);
}
return 0;
}
EDIT:
Key-logger? Nah, I am doing console network chat. Currently server and client can chat with each-other. When new message is received or sent, it is saved in "vector<\string> chat" and console is refreshed below code:
void show_chat(){
system("cls");
for(unsigned int i =0;i<chat.size();i++){
cout << "[" << date[i].tm_hour << ":" << date[i].tm_min << ":" << date[i].tm_sec << "] " << chat[i] << endl;
}
cout << "Input: ";
}
So there is a problem if new message is received while user is writing his own message. Part of the message written before message system("cls") is lost on the screen.
To do what you want, you will need to incorporate a message queue and update method.
Can you do it the way you have presented? Sure, but it's going to be a major pain and there's no way to do this with cin.
Simply have a message queue on both sides, a current status of each client(able_to_receive_messages, unable, etc), and an update method that is called by each client is run after the user is once again able to receive messages.
I have two threads in C++. One thread called alarm thread runs the function raiseAlarm() and the other thread called print thread runs the function called printMetrics. At a fixed interval, raiseAlarm sets an atomic variable to true. When the variable is true, printMetrics thread, which is spinning on the value of this atomic variable, prints some data. When I run this application, nothing happens. But if I put a cout anywhere in raiseAlarm, everything works fine. Why?
void Client::raiseAlarm()
{
bool no = false;
while(!stop.load(std::memory_order_acquire))
{
//cout << "about to sleep\n";
this_thread::sleep_for(std::chrono::seconds(captureInterval));
while(!alarm.compare_exchange_weak(no, true, std::memory_order_acq_rel))
{
no = false;
}
}
}
void Client::printMetrics()
{
bool yes = true;
while(!stop.load(std::memory_order_acquire))
{
while(!alarm.compare_exchange_weak(yes, false, std::memory_order_acq_rel) )
{
yes = true;
}
cout << "Msgs Rcvd: " << metrics.rcv_total.load(std::memory_order_acquire);
cout << "Msgs Sent: " << metrics.snd_total.load(std::memory_order_acquire);
cout << "Min latency: " << metrics.min_latency.load(std::memory_order_acquire);
cout << "Max latency: " << metrics.max_latency.load(std::memory_order_acquire);
metrics.reset();
}
}
Just a suggestion because I'm not so savvy with concurrency in C++, but make sure you don't forget to flush your output stream. Either stick a cout << flush; after all of your cout lines or add an << endl to each one (which will automatically flush your stream).
After failing to get any help in the SFML forums, I've decided to see if anyone here can be of any help. I have an application which updates itself through a TCP connection to a server application. This works perfectly fine, except for one specific packet transmission, in which the packet is somehow changed. The server sends a packet containing the number 1:
pack << sf::Uint8(1);
ClientSocket.Send(pack);
(Where pack is of type sf::Packet and ClientSocket is of type sf::SocketTCP)
Stepping through with my debugger does in fact confirm that these lines are executed, and that the next Receive call in my client is the next few lines:
sock.Receive(pack);
sf::Uint8 conf;
pack >> conf;
(Where pack is once again an sf::Packet, and sock is a SocketTCP)
However, somehow in my client, conf is showing up as having a value of zero (my debugger confirms this) and it acts as so (the next line switches depending on the value). I am running both applications on the same machine, and they are both reading each other as "127.0.0.1", so the packets (if I understand correctly) aren't going through my router, or really ever leaving my machine. Any ideas on why my packets are being corrupted?
For the record, in case it's any help, I'm using SFML 1.6 and my application in being run on a Debian Squeeze Linux machine.
EDIT: Per request, here is some more code from my application.
First, the portion of my client specifically relating to this updater:
cout << "Connecting to update server." << endl;
sf::IpAddress server = sf::IpAddress::LocalHost;
sf::TcpSocket sock;
if (sock.connect(server, PORT, sf::seconds(20.0f)) != sf::Socket::Done)
return false;
cout << "Connected. Searching for updates for updater." << endl;
sf::Packet pack;
std::string lastUpdate = getLastUpdate();
#ifdef __WXGTK__
pack << "uupdate" << lastUpdate << sf::Uint8(1);
#elif defined(__WXMSW__)
pack << "uupdate" << lastUpdate << sf::Uint8(2);
#elif defined(__WXOSX__)
pack << "uupdate" << lastUpdate << sf::Uint8(3);
#endif
sock.send(pack);
pack.clear();
sock.receive(pack); //THIS IS THE PART WHERE IT BREAKS
sf::Int32 conf;
pack >> conf;
if (conf == 1) { //There is an update!
cout << "Update found!" << endl;
pack << "begin" << sf::Uint32(512);
sock.send(pack);
pack.clear();
sock.receive(pack);
pack >> conf;
if (conf == 0) { //No errors
wxFileOutputStream* out = new wxFileOutputStream(wxString(UPDATER, StrConv).append(".temp"));
char* data = new char[512];
while (data != chara("done") && data != chara("error")) {
sock.receive(pack);
sf::Int32 size;
pack >> size;
data = const_cast<char*>((const char*)pack.getData());
out->Write(data, size);
}
out->Close();
if (data == chara("done"))
wxCopyFile(wxString(UPDATER, StrConv).append(".temp"), wxString(UPDATER, StrConv));
wxRemoveFile(wxString(UPDATER, StrConv).append(".temp"));
}
}
cout << "Updater is up-to-date. Executing updater." << endl;
sock.disconnect();
bool success;
if (wxTheApp->argc == 1)
success = wxExecute(wxT(UPDATER));
else
success = wxExecute(wxString(UPDATER, StrConv).append(wxTheApp->argv[1]));
return success;
And then the portion of the server relating to these updates:
//ClientSocket has already been initalised by way of a TcpListener
cout << "Checking for updater patches for client at " << ClientAddress.toString() << endl;
std::string lastUpdate;
pack >> lastUpdate;
sf::Uint8 os;
pack >> os;
//Check last time updater was changed
struct tm* clock;
struct stat attribs;
if (os == 1)
stat("Linux/Updater", &attribs);
else if (os == 2)
stat("Windows/Updater.exe", &attribs);
else if (os == 3)
stat("Mac/Updater", &attribs);
clock = gmtime(&(attribs.st_mtime));
time_t lastWrite = mktime(clock);
time_t clientUpdate = stringToNumber<time_t>(lastUpdate.c_str());
if (lastWrite > clientUpdate) {
cout << "Found updater patches for client at " << ClientAddress.toString() << endl;
pack << sf::Int32(1);
ClientSocket->send(pack); //THIS IS THE PART WHERE IT BREAKS
pack.clear();
ClientSocket->receive(pack);
std::string mes;
pack >> mes;
if (mes != "begin") {
cerr << "Client at " << ClientAddress.toString() << " sent unrecognised message: " << mes << ". Ending conversation." << endl;
ClientSocket->disconnect();
return false;
}
sf::Uint32 size;
pack >> size;
cout << "Beginning to send updater patch to " << ClientAddress.toString() << endl;
ifstream in;
if (os == 1)
in.open(chara("Linux/Updater"), ios_base::in | ios_base::binary);
else if (os == 2)
in.open(chara("Windows/Updater.exe"), ios_base::in | ios_base::binary);
else if (os == 3)
in.open(chara("Mac/Updater"), ios_base::in | ios_base::binary);
if (in.fail()) {
pack << sf::Uint8(1);
ClientSocket->send(pack);
cerr << "Failed to open updater at request of " << ClientAddress.toString() << ". Closing connection." << endl;
ClientSocket->disconnect();
return false;
}
pack << sf::Uint8(0);
ClientSocket->send(pack);
pack.clear();
//Get length of file
in.seekg(0, ios::end);
int length = in.tellg();
in.seekg(0, ios::end);
char* buf = new char[size];
for (unsigned int i = 0; i < length / size; i++) { //Read and send every `size`-sized block we can
in.read(buf, size);
pack << sf::Int32(size) << buf;
ClientSocket->send(pack);
}
in.read(buf, length % size);
pack << sf::Int32(length % size) << buf;
ClientSocket->send(pack);
pack.clear();
pack << "done";
ClientSocket->send(pack);
pack.clear();
} else {
pack << sf::Int8(0);
ClientSocket->send(pack);
}
EDIT: I know it's been almost a month since there have been any posts on here, but I'm still having issues with this. I'm at wit's end on how to solve this.
This is not really an answer but I can't add a comment on the question so...
SFML 1.6 is not maintained and if there is an issue with SFML itself it might already be solved in version 2.0. You can download the RC here.
So, turns out the problem was rather simple. You know how I added lots of pack.clear() lines in? Turns out I forgot to add one between receiving the original data and sending the original data on the server. So my packet still had data left over from the first call to sock.receive(pack) (which was a few lines above the start of the code from the server posted above). It took me this long to see that. Put in a call to pack.clear() and the problem went away.
In C++, which would be faster if repeated, say, 5000 times:
cout << "text!" << endl;
or
my_text_file << "text!" << endl;
(writing to a file vs. cout-ing to the console)
Edit:
I ask because when writing to the console, you see all the text being printed which seems like it would slow down the loop. In a file, you arn't seeing the text being printed, which seems as if it would take less time.
Just tested it:
Console: > 2000 ms using endl and \n
File: 40 ms with endl and 4 ms with \n
Writing to a file would be much faster. This is especially true since you are flushing the buffer after every line with endl.
On a side note, you could speed the printing significantly by doing repeating cout << "text!\n"; 5000 times, then flushing the buffer using flush().
It's not that much faster...
A test of 1 million couts with endl (clear buffer):
Results:
console cout time: 2.87001
file cout time: 2.33776
Code:
class Timer
{
struct timespec startTime, endTime;
double sec;
public:
void start();
void stop();
double getSec();
};
void Timer::start()
{
clock_gettime(CLOCK_MONOTONIC, &startTime);
}
void Timer::stop()
{
clock_gettime(CLOCK_MONOTONIC, &endTime);
sec = (endTime.tv_sec - startTime.tv_sec);
sec += (endTime.tv_nsec - startTime.tv_nsec) / 1000000000.0;
}
double Timer::getSec()
{
return sec;
}
int main(){
int ntests = 1000000;
Timer t1 = Timer(), t2 = Timer();
t1.start();
for(int c=0;c<ntests;c++)
{
cout << "0" << endl;
}
t1.stop();
ofstream out("out.txt");
streambuf *coutbuf = cout.rdbuf();
cout.rdbuf(out.rdbuf());
t2.start();
for(int c=0;c<ntests;c++)
{
cout << "0" << endl;
}
t2.stop();
cout.rdbuf(coutbuf);
cout << "console cout time: " << t1.getSec() << endl;
cout << "file cout time: " << t2.getSec() << endl;
}
Build and run:
g++ test.cpp -o test -lrt && ./test && rm out.txt
In addition to console I/O generally being relatively slow, the default configuration of the standard streams cout and cin has some issues that will greatly slow performance if not corrected.
The reason is that the standard mandates that, by default, cout and cin from the C++ iostream library should work alongside stdout and stdin from the C stdio library in the expected way.
This basically means that cout and cin can't do any buffering at all in its internal streambufs and basically forwards all I/O operations over to the C library.
If you want to do anything resembling high performance I/O with the standard streams, you need to turn off this synchronization with
std::ios_base::sync_with_stdio(false);
before doing any I/O.
Writing the same amount of data, with the same buffer size to the console will most definitely be faster than writing to a file.
You can speed up your write speed (both for console output, and file output) by not writing out the buffer with every line (i.e.- don't use std::endl after every line, as it both adds an endline to the stream, and writes the buffer). Instead use "\n" unless you need to ensure the buffer is output for some reason.
I'm modifying the stock quoter example from the wustl CORBA release. The assignment is to implement a reply handler for the StockFactory class that handles calls to get_stock()
Here's my FactoryHandler implementation:
FactoryHandler_i.h:
#ifndef TAO_TUTORIALS_QUOTER_AMI_CLIENT_FACTORYHANDLER_I_H
#define TAO_TUTORIALS_QUOTER_AMI_CLIENT_FACTORYHANDLER_I_H
#include "QuoterS.h"
class Stock_Factory_Handler_i : public POA_Quoter::AMI_Stock_FactoryHandler
{
public:
Stock_Factory_Handler_i (int *response_count, ::Quoter::Stock_var& result);
void get_stock (::Quoter::Stock_ptr ami_return_val);
void get_stock_excep (::Messaging::ExceptionHolder * excep_holder);
private:
int *response_count_;
::Quoter::Stock_var& result_;
};
#endif /* TAO_TUTORIALS_QUOTER_AMI_CLIENT_HANDLER_I_H */
FactoryHandler_i.cpp:
#include "FactoryHandler_i.h"
#include "ace/streams.h"
Stock_Factory_Handler_i::
Stock_Factory_Handler_i (int *response_count, ::Quoter::Stock_var& result)
: response_count_ (response_count), result_ (result)
{
}
void
Stock_Factory_Handler_i::get_stock (::Quoter::Stock_ptr ami_return_val)
{
cout << "storing result" << endl;
result_ = ami_return_val;
(*this->response_count_)++;
}
void
Stock_Factory_Handler_i::get_stock_excep (::Messaging::ExceptionHolder * excep_holder)
{
// We ignore the exception, but this counts as a response, otherwise
// the application would not finish.
cerr << "Exception raised while getting stock"
<< endl;
(*this->response_count_)++;
}
And the client.cpp, from just before the part where changes have been made:
// ...
// Create and activate the handler...
int response_count = 0;
Single_Query_Stock_Handler_i handler_i (&response_count);
Quoter::AMI_Single_Query_StockHandler_var handler =
handler_i._this ();
// Create and activate the factory handler...
Quoter::Stock_var result;
Stock_Factory_Handler_i factory_handler_i (&response_count, result);
Quoter::AMI_Stock_FactoryHandler_var factory_handler =
factory_handler_i._this();
// Send all the requests, careful with error handling
int request_count = 0;
for (int i = 2; i != argc+1; ++i) {
try {
// Get the stock object
cout << "looking up stock symbol " << argv[i] << endl;
factory->sendc_get_stock (factory_handler.in (), argv[i]);
sleep(3); // wait for a response
cout << "converting result" << endl;
Quoter::Single_Query_Stock_var stock =
Quoter::Single_Query_Stock::_narrow (result.in ());
cout << "checking result" << endl;
CORBA::Any any;
any <<= stock;
CORBA::TypeCode_var tc = any.type();
cout << tc->kind() << endl;
if (CORBA::is_nil (stock.in ())) {
cerr << "Cannot get single query interface for <"
<< argv[i] << ">" << endl;
continue;
}
cout << "reading result" << endl;
stock->sendc_get_price_and_names (handler.in ());
request_count++;
}
catch (Quoter::Invalid_Stock_Symbol &) {
cerr << "Invalid stock symbol <"
<< argv[i] << ">" << endl;
}
}
while (response_count < 2 * request_count // multiply by 2 because both handlers increment response_count
&& orb->work_pending ()) {
orb->perform_work ();
}
// ...
When running the client, the output is:
looking up stock symbol MSFT
converting result
checking result
14
Cannot get single query interface for <MSFT>
(The 14 is the typecode for Stock, that's only for debugging)
Notably missing from the above is the "storing result" message that's supposed to be printed in the FactoryHandler's get_stock() callback method. I'm at a loss as to why, since the sendc_get_stock() method doesn't produce any (immediate) errors and is basically just a copy of the StockHandler's code, and from there it's the responsibility of the AMI/ORB interface to make the callback. But the original example (with a StockHandler only) works fine.
What am I doing wrong (and how do I fix it)?
EDIT: another bit of information: on the server side, StockFactory's get_stock() method does get called.
Sorry, I've no aswer for you. But a hint, ask your question at TOA's maling list at http://www.cs.wustl.edu/~schmidt/ACE-mail.html
HTH
I think that your problem is that work_pending returns true only if the ORB has immediate work to do, so it returns false in the time after your client sent his request and before the server sends his reply.
To validate that, simply remove the && orb->work_pending() condition from the loop, and use the version of perform_work that takes a timeout argument.