Link to home
Start Free TrialLog in
Avatar of vinawy
vinawyFlag for Singapore

asked on

C++ winsock sendto() function

Hi I will like to ask the following:
1) winsock sendto() function what is the default and max send buffer size. I want to send datagram of size 4096 bytes do I need to fragment before sending out or calling sendto() a few times?

2) recvfrom() what is the default and max buffer size?

Thanks, will appreciate any advice as I cant seem to find any info off msdn.
Avatar of Infinity08
Infinity08
Flag of Belgium image

Both with sendto and recvfrom, you provide your own buffer with your own size. The only limit is the size of the memory available ;)
>> I want to send datagram of size 4096 bytes do I need to fragment before sending out or calling sendto() a few times?
No, just send the full buffer and let the appropriate OSI layer take care of all that for you. You are currently at the application layer.
http://en.wikipedia.org/wiki/OSI_model
Avatar of vinawy

ASKER

Hi tks for the replies, say codewise in C++ winsock do i need to set socket options for the send and recv size?

I cannot seem to send over 1024 bytes and i need to send at least 4096 bytes. Pls advice. Thank you.
Avatar of vinawy

ASKER

I came across someone writing that sending data across the ethernet (which im doing right now) the max size is as follows:

"Max Tx Unit (MTU) is 1500bytes for ethernet and 8000bytes for loopback address (127.0.0.1)
Usable payload = 1500-20(IPV4)-8(UDP) = 1472."

so my question is if it is posssible for me to send 4096 bytes of data simply by using winsock sendto() function without 'fragmentation on the application layer'?

Tks.
It seems there are some caveats to message size...
http://msdn2.microsoft.com/en-us/library/ms740148(VS.85).aspx

"The sendto function is used to write outgoing data on a socket. For message-oriented sockets, care must be taken not to exceed the maximum packet size of the underlying subnets, which can be obtained by using getsockopt to retrieve the value of socket option SO_MAX_MSG_SIZE. If the data is too long to pass atomically through the underlying protocol, the error WSAEMSGSIZE is returned and no data is transmitted."

This being the case you may very well need to write your data in blocks.

Avatar of vinawy

ASKER

>>This being the case you may very well need to write your data in blocks.

Do you mean that say I have a 4096 bytes data, I will have to split it up in blocks of 1024 and send it over by calling sendto() function 4 times? then at the receiving side I have to implement an algorithm to reassemble the full data?.

I'm wondering if I am able to send 4096 bytes in one chunk and receiving it in just one datagram through sendto() and recvfrom().

Tks.
>> I'm wondering if I am able to send 4096 bytes in one chunk and receiving it in just one datagram through sendto() and recvfrom().
The MSDN seems pretty clear on this, it all depends upon the result of the call to getsockopt. Implementing code to send in blocks isn't going to be hard. I have provided a demo below. It is NOT a working example of sending via sockets, it is just an example of how you could do this. Clearly you'll need to write the specific code to make it work.

>> I have to implement an algorithm to reassemble the full data?.
The MSDN states for recvfrom, "If no error occurs, recvfrom returns the number of bytes received. If the connection has been gracefully closed, the return value is zero. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code can be retrieved by calling WSAGetLastError." So, you'll have to keep reading from recvfrom until you have managed to read all the data for that block. You can request 4KB but you'll only read what is available, which may or may not be the full 4KB.

I hope this helps.

-Rx.


typedef int SOCKET;
 
#define MAX_BLOCK_SIZE 1024 // This should be obtained by calling getsockopt SO_MAX_MSG_SIZE
 
int sendto(
	SOCKET s,
	const char* buf,
	int len,
	int flags,
	const struct sockaddr* to,
	int tolen
)
{
	return len;
}
 
int MySendTo(
	SOCKET s,
	const char* buf,
	int len,
	int flags,
	const struct sockaddr* to,
	int tolen
)
{
	int tosend = len;
 
	while(tosend > 0)
	{
		int block = tosend > MAX_BLOCK_SIZE ? MAX_BLOCK_SIZE : tosend;
 
		if(tosend > 0)
		{
			int sentok = sendto(s, (buf+(len - tosend)), block, flags, to, tolen);
			if(sentok < 0) { break; }
			tosend -= sentok;
		}
	}
 
	return (len - tosend);
}
 
int main(void)
{
	char buf[0x1010] = {0};
	SOCKET s = 0;
	MySendTo(s, buf, sizeof(buf)/sizeof(buf[0]), 0, 0, 0);
	return 0;
}

Open in new window

If you get EMSGSIZE as error, then that means that your socket needs messages to be sent atomically, and then the maximum size depends on the maximum packet size (see MTU).

However, normally, sendto will return how many bytes it sent successfully. You'll then have to skip that many bytes in your buffer, and call sendto again, etc.

It is good practice to send in chunks of 1024 bytes (or lower if the underlying network doesn't support it) though ... Something like evilrix showed.
ASKER CERTIFIED SOLUTION
Avatar of evilrix
evilrix
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of vinawy

ASKER

Cool It worked