flush buffer in a boost::asio program - c++

Basically I am writing a simple program using the boost socket library... I have two programs a client and a server. the server waits for a connection from the client and when it finds one the client sends the server a message and the server prints out, this works the first time the client queries the server but after a while an strange pattern begins lets say our server was running and I used the client program two times by executing:
./client localhost name message
./client localhost name test
the output 0f the server would first be:
name: message
however next it would display
name: testage
I don't know why this is happening but I know it must be the server, because the the clients each send a packet independently the server just prints it out... I'm thinking that this has something to do with the socket buffer not being flushed or something of that nature...
anyway heres the sourcecode:
client.cpp
http://pastebin.com/hWpLNqnW
server.cpp
http://pastebin.com/Q4esYwdc

The read_some call in the server returns the number of bytes read. You should use that value and use it to null terminate the buffer. Something along these lines:
int len = connection.read_some(boost::asio::buffer(buf), error);
buf[len] = '\0';
In the first message, the buffer may have been initialized with zeros. The next time, though, it would contain the same contents as the previous iteration. Note that the strcpy(buf,""); call only ends up setting the first byte of buf to zero.

Related

C++ HTTP client hangs on read() call after GET request

std::string HTTPrequest = "GET /index.html HTTP/1.1\r\nHost: www.yahoo.com\r\nConnection: close\r\n\r\n";
write(socket, HTTPrequest.c_str(), sizeof(HTTPrequest));
char pageReceived[4096];
int bytesReceived = read(socket, pageReceived, 4096);
I've got an HTTP client program that I run from my terminal. I've also got a webserver program. Using the webserver as a test, I can verify that the socket creation and attachment works correctly.
I create the request as shown above, then write to the socket. Using print statements, I can see that the code moves beyond the write call. However, it hangs on the read call.
I can't figure out what's going on - my formatting looks correct on the request.
Any ideas? Everything seems to work perfectly fine when I connect to my webserver, but both www.yahoo.com and www.google.com cause a hang. I'm on Linux.
In C and C++, sizeof gives you the number of bytes required to hold a type, regardless of its contents. So you are not sending the full request, only sizeof(std::string) bytes. You want HTTPRequest.size() (which gives you the number of bytes the value stored in HTTPRequest takes), not sizeof(HTTPrequest) (which gives you the number of bytes a std::string itself requires).

Socket error in C using read and write functions

I am attempting to read and write to a socket using linux networking programming in C. I make successful calls to "write" and "read" in the client and server programs respectively.
The part I am having difficulty understanding is that on my client program, I loop and call the write 5 different times, on the server, I loop and call the read 5 different times.
This is the expected output:
MSG: I got your message MSG: I got your message MSG: I got your message MSG: I got your message MSG: I got your message
This is the actual output:
MSG: I got your messageI got your messageMSG: I got your messageI got your messageMSG: I got your messageMSG: MSG:
As you can see the expected output and the actual output are different. It looks like the client is able to call "write" twice before it is actually sent.
This is what I have for the client code
for(int i=0;i<5;i++)
{
int n = write(ssocket.socketFileDescriptor,"I got your message",18);
cout<<n<<" number of bytes written."<<endl;
if (n < 0) socketError("ERROR writing to socket");
}
This is the server code:
void* run(void* arg)
{
ServerSocket* ss = (ServerSocket*)arg;
//while(true)
for(int i=0;i<5;i++)
{
char buffer[256];
bzero(buffer,256);
int n = read(ss->newsockfd,buffer,256);
printf("MSG: %s",buffer);
}
close(ss->newsockfd);
}
This is an addition to the question below which is out of date at this point.
Am I missing a call to flush or something?
Simulate Java's Thread class in C++
Your client and server are just not coordinated. The client writes the message 5 times as quickly as it can, and the server reads five times as quickly as it can. In your example output, evidently on your first call to read() the client has sent the message twice, and on the second call to read() it's sent it a further two times. You read() up to 256 characters, and each time you call it, it will just attempt to read anything that's currently in the buffer. If the client has send multiple messages by that time, read() will just grab everything.
You typically need some type of synchronization, e.g. after you send one message, your client waits for the server to send "OK" or something similar before it sends the second message. Short of that, you can use some kind of end-of-message marker (such as a newline) so the server can differentiate them, if you have a very simple communication format.

Server programming in C++

I'd like to make a chatting program using win socket in c/c++. (I am totally newbie.)
The first question is about how to check if the client receives packets from server.
For instance, a server sends "aaaa" to a client.
And if the client doesn't receive packet "aaaa", the server should re-send the packet again.(I think). However, I don't know how to check it out.
Here is my thought blow.
First case.
Server --- "aaaa" ---> Client.
Server will be checking a sort of time waiting confirm msg from the client.
Client --- "I received it" ---> Server.
Server won't re-send the packet.
The other case.
Server --- "aaaa" ---> Client.
Server is waiting for client msg until time out
Server --- "aaaa" ---> Client again.
But these are probably inappropriate.
Look at second case. Server is waiting a msg from client for a while.
And if time's out, server will re-send a packet again.
In this case, client might receive the packet twice.
Second question is how to send unlimited size packet.
A book says packet should have a type, size, and msg.
Following it, I can only send msg with the certain size.
But i want to send msg like 1Mbytes or more.(unlimited)
How to do that?
Anyone have any good link or explain correct logic to me as easy as possible.
Thanks.
Use TCP. Think "messages" at the application level, not packets.
TCP already handles network-level packet data, error checking & resending lost packets. It presents this to the application as a "stream" of bytes, but without necessarily guaranteed delivery (since either end can be forcibly disconnected).
So at the application level, you need to handle Message Receipts & buffering -- with a re-connecting client able to request previous messages, which they hadn't (yet) correctly received.
Here are some data structures:
class or struct Message {
int type; // const MESSAGE.
int messageNumber; // sequentially incrementing.
int size; // 4 bytes, probably signed; allows up to 2GB data.
byte[] data;
}
class or struct Receipt {
int type; // const RECEIPT.
int messageNumber; // last #, successfully received.
}
You may also want a Connect/ Hello and perhaps a Disconnect/ Goodbye handshake.
class Connect {
int type; // const CONNECT.
int lastReceivedMsgNo; // last #, successfully received.
// plus, who they are?
short nameLen;
char[] name;
}
etc.
If you can be really simple & don't need to buffer/ re-send messages to re-connecting clients, it's even simpler.
You could also adopt a "uniform message structure" which had TYPE and SIZE (4-byte int) as the first two fields of every message or handshake. This might help standardize your routines for handling these, at the expense of some redundancy (eg in 'name' field-sizes).
For first part, have a look over TCP.
It provides a ordered and reliable packet transfer. Plus you can have lot of customizations in it by implementing it yourself using UDP.
Broadly, what it does is,
Server:
1. Numbers each packet and sends it
2. Waits for acknowledge of a specific packet number. And then re-transmits the lost packets.
Client:
1. Receives a packet and maintains a buffer (sliding window)
2. It keeps on collecting packets in buffer until the buffer overflows or a wrong sequenced packet arrives. As soon as it happens, the packets with right sequence are 'delivered', and the sequence number of last correct packet is send with acknowledgement.
For second part:
I would use HTTP for it.
With some modifications. Like you should have some very unique indicator to tell client that transmission is complete now, etc

C/C++ server not sending last few lines of file

I am writing a simple server in C/C++. I have everything mostly complete, but there is one problem. The server fails to send the last three lines of a file to a client. I assume I am closing the socket connection prematurely, but my attempts to remedy this have failed. For example, calling
shutdown(clientSckt, SHUT_RDWR);
right before calling the close() method for the client socket. And adding a latency to the socket parameters like so:
struct linger l;
l.l_onoff = 1;
l.l_linger = 1;
setsockopt(clientSckt, SOL_SOCKET, SO_LINGER, &l, sizeof(l));
after it has been opened. But neither of these seem to work. The server writes everything with no errors, but the client is not receiving everything.
From vague memory:
a) if you want to use SO_LINGER, use close().
b) more robust is do a half shutdown
shutdown(clientSckt, SHUT_WR)
and then read() until you get a 0.
It turns out, I forgot to add the character length of the header to the length of the file I was sending over. Hence, the client was closing the connection before the server had sent everything over.

boost::asio::async_read_until - Does not read until four messages have been sent

I'm trying to learn boost::asio by writing a simple client which sends strings to an echo server. I have tested the echo server with telnet and it works great, but my boost::asio client is acting weird. async_read_until doesn't seem to read/call handler until four messages have been sent (and returned by the echo server). The output of the client maybe explain this better (I removed the newline after each value):
gurka#x:~/private/code/test$ ./test localhost 2001
Hostname resolved.
Connected to server.
Starting write
Starting read_until
Writting[1]
Writting[2]
Writting[3]
Writting[4]
Read[1]
Writting[5]
Read[2]
Writting[6]
When the connection have been made I have two calls:
boost::asio::async_write(mSocket, mOutgoingBuffer, boost::bind(&Connection::writeToServer, this, boost::asio::placeholders::error));
boost::asio::async_read_until(mSocket, mIncomingBuffer, "\n", boost::bind(&Connection::readFromServer, this, boost::asio::placeholders::error));
writeToServer and readFromServer just prints Writting/Read and the value it's writting/read and then does the async_write/async_read_until call again, with exacly same parameters. The writeToServer takes it messages to send from a queue which I have filled with "1\n".."6\n".
I don't think the error is in the echo server since I can see that it read and writes back all 6 values, in order. And it as I said before, it works perfect using telnet. So, why is async_read_until "delayed" by 4 messages? I've tried sending longer strings and it's the same thing.