TCP Streaming
Hi, I'm making a basic library to make client/server apps via TCP. The thing is, if my send()'s never exceed the MTU limit, can I be 100% sure that the recv() call on the remote side will have the same data in the buffer ? Or I must create a working buffer big enough to fit 2 packets to rebuild the data on the otherside, assuming i could have partial headers, and partial data? Thanks...any suggestions are welcome.
Quote:
Original post by pnroach
another question here ? )
what is MTU limit?
just wondering...
MTU means Maximum Transmission Unit, the largest physical packet size, measured in bytes, that a network can transmit. Any messages larger than the MTU are divided into smaller packets before being sent.
56k have 576 bytes MTU
Cable/DSL have 1024 bytes MTU
and I think on Lan you can go to 8k...not sure
@md_lasalle
thanx! very useful! what about situation when i send stuff to myself (127.0.0.1) to test something? does this MTU parameter then have any meaning?
thanx! very useful! what about situation when i send stuff to myself (127.0.0.1) to test something? does this MTU parameter then have any meaning?
It mostly depends on hardware, it would probably be the same as LAN.
I was reading something interesting about MTU and the Nagel algorythm. If you don't send() enough byte to fill the MTU limit, it will wait until it is filled before sending the data. It was created to reduced bandwidth usage from lots of small send().
But if you dont want it to wait, you can setup on your socket the TCP_NODELAY option...but you will waste lot of bandwidth, it depends on what you do with it probably.
I was reading something interesting about MTU and the Nagel algorythm. If you don't send() enough byte to fill the MTU limit, it will wait until it is filled before sending the data. It was created to reduced bandwidth usage from lots of small send().
But if you dont want it to wait, you can setup on your socket the TCP_NODELAY option...but you will waste lot of bandwidth, it depends on what you do with it probably.
Unless you overfill your send() buffer, the data will arrive at the other end in the order you sent it. You can't guarantee that one send() will be picked up in one recv(), though; 'packets' can get split or amalgamated by TCP. You need to have some sort of way of making sure you get whole messages again (usually just a length field at the front of each one).
You can never be sure that the recv() packet will be the same size (or even same count) as a the send() packets. TCP is a stream. The sending implementation, network card, routers on the way, or recieiving implementation may choose to combine or split the data stream any way they want to, for efficiency or other reasons.
You don't need buffer space for more than one packet -- the kernel will buffer for you, too. Thus, read data into a buffer that's at least as large as the biggest packet. Attempt to parse the packet (knowing how much is in the buffer) -- if success, then remove that much data from the buffer, shifting the rest of data (if any) down towards the beginning. Repeat.
Code that implements this as an asynchronous state machine can be found in the MIT license Etwork network library.
You don't need buffer space for more than one packet -- the kernel will buffer for you, too. Thus, read data into a buffer that's at least as large as the biggest packet. Attempt to parse the packet (knowing how much is in the buffer) -- if success, then remove that much data from the buffer, shifting the rest of data (if any) down towards the beginning. Repeat.
Code that implements this as an asynchronous state machine can be found in the MIT license Etwork network library.
enum Bool { True, False, FileNotFound };
something weird seems to be going on with my data receiving routine. i send a block of data with a header attached to it showing the size of that block -- this all goes in one piece. then on the server
side i first receive the header and allocate storage for the data itself. my debug log shows very awkward results though data is transferred correctly.
std::string receive()
{
int header;
int res;
std::string ret;
//we first figure out how big of a packet we are expecting
res = ::recv(socket_,(char*)&header,sizeof(int),0);
if( res == 0 ) throw socket_exception("connection closed",WSAGetLastError());
if( res == SOCKET_ERROR ) throw socket_exception("recv failed!",WSAGetLastError());
//here we allocate just enough of memory to hold the received data
boost::scoped_ptr<char> data(new char[header]);
std::cout << "we have to receive " << header << " bytes\n";
res == ::recv(socket_,data.get(),header,0);
if( res == 0 ) throw socket_exception("connection closed",WSAGetLastError());
if( res == SOCKET_ERROR ) throw socket_exception("recv failed!",WSAGetLastError());
std::cout << res << " bytes received\n";
ret.assign(data.get());
return ret;
}
OUTPUT
we have to receive 953 bytes
4 bytes received
the return value of receive() is correct! i sent XML document in a string form on the client side and received this same document on the server... but why the results of
recv() are so weird then?
i wouldn't really care about this too much but i am planning on changing this routine a bit in order to handle partial data receiving. to do this i really need to know how
much of data i receive.
suggestions?
side i first receive the header and allocate storage for the data itself. my debug log shows very awkward results though data is transferred correctly.
std::string receive()
{
int header;
int res;
std::string ret;
//we first figure out how big of a packet we are expecting
res = ::recv(socket_,(char*)&header,sizeof(int),0);
if( res == 0 ) throw socket_exception("connection closed",WSAGetLastError());
if( res == SOCKET_ERROR ) throw socket_exception("recv failed!",WSAGetLastError());
//here we allocate just enough of memory to hold the received data
boost::scoped_ptr<char> data(new char[header]);
std::cout << "we have to receive " << header << " bytes\n";
res == ::recv(socket_,data.get(),header,0);
if( res == 0 ) throw socket_exception("connection closed",WSAGetLastError());
if( res == SOCKET_ERROR ) throw socket_exception("recv failed!",WSAGetLastError());
std::cout << res << " bytes received\n";
ret.assign(data.get());
return ret;
}
OUTPUT
we have to receive 953 bytes
4 bytes received
the return value of receive() is correct! i sent XML document in a string form on the client side and received this same document on the server... but why the results of
recv() are so weird then?
i wouldn't really care about this too much but i am planning on changing this routine a bit in order to handle partial data receiving. to do this i really need to know how
much of data i receive.
suggestions?
res == ::recv(socket_,data.get(),header,0);
I believe you wanted the assignment operator (=) here :)
I believe you wanted the assignment operator (=) here :)
_______________The essence of balance is detachment. To embrace a cause, to grow fond or spiteful, is to lose one''s balance after which, no action can be trusted. Our burden is not for the dependent of spirit. - Mayar, Third Keeper
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement
Recommended Tutorials
Advertisement