It seems that I'm not able to receive UDP Packets with a message bigger than 4096 bytes.
Where can I change this limit?
Is it OS or network adapter related?
I got this issue on my Windows Server 2012 R2 while it's working fine on my Windows 8.1 pc.
Any hint would be much appreciated.
You need to raise the socket send buffer size at the sender, and the socket receive buffer size at the receiver. However the generally accepted practical limit on UDP payload size is 534 bytes. Above that, they can be fragmented, and if a fragment doesn't arrive the entire datagram is lost.
According to the Microsoft documentation for socket options, there's a SO_MAX_MSG_SIZE option that is "the maximum outbound message size for message-oriented sockets supported by the protocol." UDP sockets are "message-oriented sockets" (as opposed to "stream-oriented sockets"; TCP sockets are stream-oriented).
This suggests that there is a maximum message size imposed by the operating system. Sadly, that page does not say "yes" in the "Set" column for the SO_MAX_MSG_SIZE row, so your program can't override that maximum.
Related
I use Embarcadero RAD Studio & Indy and I have a problem.
I am using component IdUDPServer and try to send file via UDP messages.
The file is successfully transferred if it is not large.
However, the error message “Package Size Too Big” appears if the file is large.
My code:
FileAPP->ReadBuffer(Buffer, Size);
IdUDPServer1->SendBuffer("10.6.1.255", 34004, RawToBytes(&Buffer, Size));
I see two ways to solve this problem:
1) Compose small messages and send these messages in a loop.
This is an easy way to solve the problem, however I will need to fix the remote application.
This is currently difficult. I do not have much time.
2)I want to find a condition in the source code where this error message is generated.
Maybe I can fix the condition and it will work for my specific task.
I have added some pictures. This is all the information that I now have.
Screenshots from help file: Picture 1, Picture 2, Picture 3
Error message: Picture 4
Please help me if you know the solution.
"Package Size Too Big" means you tried to send a datagram that is too large for UDP to handle. UDP has an effective max limit of 65507 bytes of payload data per datagram. You can't send a large file in a single datagram, it just won't fit.
So yes, you will have to break up your file into smaller chucks that are sent in separate datagrams. And as such, because UDP is connection-less and does not guarantee delivery, you will also have to solve the issues of lost packets and out-of-order packets. You will have to put a rolling sequence number inside your packets so that the receiver can save packets in the proper order. And you will have to implement a re-transmission mechanism to re-send lost packets that the receiver did not receive.
I would suggest not using TIdUDPClient/TIdUDPServer to implement file transfers manually, if possible. Indy has TIdTrivialFTP/TIdTrivialFTPServer components that implement the standardized UDP-based TFTP protocol, which handles these kind of details for you. By default, TFTP has a limit of ~32MB per file (512 bytes per datagram * 65535 datagrams max), but you can increase that limit using the TIdTrivialFTP.RequestedBlockSize property to request permission from a TFTP server to send more bytes per datagram. RequestedBlockSize is set to 1500 bytes by default, which can accommodate files up to ~93.7MB in size (though in practice it should not be set higher than 1468 bytes so TFTP datagrams won't exceed the MTU size of Ethernet packets, thus limiting the max file size closer to ~91.7MB). The RequestedBlockSize can be set as high as 65464 bytes per datagram to handle files up to ~3.9GB (at the risk of fragmenting UDP packets at the IP layer).
It is also possible for TFTP to handle unlimited file sizes with smaller datagram sizes, though TidTrivialFTP/TIdTrivialFTPServer do not currently implement this, because this behavior is not currently standardized in the TFTP protocol, but is commonly implemented as an extension in 3rd party implementations.
Otherwise, you should consider using TCP instead of UDP for your file transfers. TCP doesn't suffer from these problems.
I'm developing an Ethernet driver in Linux platform. I found that when a TCP retransmission occurred, the TCP payloads of multiple retransmission packets referring to the same sequence number packets were different. I can't understand why it would happen. In my driver, I just allocated a normal network device without any specific flags. By the way, the TCP checksum field was also wrong in these retransmission packets, however, the checksum in all the other types of TCP packets was right, such as SYNC, ACK, and DUP ACK.
I captured the packets by wireshark, and it means the packets I captured were not handled by my driver, just from the TCP stack in Linux kernel. But when I tested with other Ethernet devices and drivers, this problem didn't happen. So my questions were like the following.
Is there any possible for TCP stack to retransmit the same packets without same payload?
Which kinds of parameters in Linux kernel would cause these problem?
How can my driver cause this problem?
Thx for all your reply.
I found the reason for this problem. It's a very very fool fault.
Due to making all the DMA buffers (in my driver it's skb->data)address aligned to 4bytes, I called a memmove function to do that. Actually, the data referred by the skb->data is shared by all the TCP/IP stack in the Kernel. So after this wrong operation, when the TCP retranmission occurs, the address referred by skb->data in TCP stack still maintains the original one. That's why the checksum based on original data seems wrong in wireshark. The codes in my driver is like the following.
u32 skb_len = skb->len;
u32 align = check_aligned(skb);
if !align
return skb;
skb_push(skb,align);
memmove(skb->data, skb->data+align, skb_len);
skb_trim(skb, skb_len);
return skb;
I hope my experience can help others to avoid this fool fault.
I have a problem - I don't know the amount of data being sent to my UDP server.
The current code is this - testing in irb:
require 'sockets'
sock = UDPSocket.new
sock.bind('0.0.0.0',41588)
sock.read # Returns nothing
sock.recvfrom(1024) # Requires length of data to be read - I don't know this
I could set recvfrom to 65535 or some other large number but this seems like an unnecessary hack.
recvfrom and recvfrom_nonblock both throw away anything after that length specified.
Am I setting the socket up incorrectly?
Note that UDP is a datagram protocol, not a stream like TCP. Each read from UDP socket dequeues one full datagram. You might pass these flags to recvfrom(2):
MSG_PEEK
This flag causes the receive operation to return
data from the beginning of the receive queue without
removing that data from the queue. Thus, a subsequent
receive call will return the same data.
MSG_WAITALL
This flag requests that the operation block until the
full request is satisfied. However, the call may still
return less data than requested if a signal is caught,
an error or disconnect occurs, or the next data to be
received is of a different type than that returned.
MSG_TRUNC
Return the real length of the packet, even when it was
longer than the passed buffer. Only valid for packet sockets.
If you really don't know how large of a packet you might get (protocol limit is 65507 bytes, see here) and don't care about doubling the number of system calls, do the MSG_PEEK first, then read exact number of bytes from the socket.
Or you can set an approximate max buffer size, say 4096, then use MSG_TRUNC to check if you lost any data.
Also note that UDP datagrams are rarely larger then 1472 - ethernet data size of 1500 minus 20 bytes of IPv4 header minus 8 bytes of UDP header - nobody likes fragmentation.
Edit:
Socket::MSG_PEEK is there, for others you can use integer values:
MSG_TRUNC 0x20
MSG_WAITALL 0x100
Look into your system headers (/usr/include/bits/socket.h on Linux) to be sure.
Looking at the documentation for Ruby's recvfrom(), the argument is a maximum length. Just provide 65535 (max length of a UDP datagram); the returned data should be the sent datagram of whatever size it happens to be, and you should be able to determine the size of it the way you would for any stringlike thing in Ruby.
I'm working on a network-related project and I am using DTLS (TLS/UDP) to secure communications.
Reading the specifications for DTLS, I've noted that DTLS requires the DF flag (Don't Fragment) to be set.
On my local network if I try to send a message bigger than 1500 bytes, nothing is sent. That makes perfect sense. On Windows the sendto() reports a success but nothing is sent.
I obviously cannot unset the DF flag manually since it is mandatory for DTLS and i'm not sure whether the 1500 bytes limit (MTU ?) could change in some situations. I guess it can.
So, my question is : "Is there a way to discover this limit ?" using APIs ?
If not, what would be the lowest possible value ?
My software runs under UNIX (Linux/MAC OSX) and Windows OSes so different solutions for each OS are welcome ;)
Many thanks.
There is a minimum MTU that must be supported - 576 bytes, including IP headers. So if you keep your packets below that, you don't have to worry about PMTU-D (that's what DNS does).
you probably need to 'auto tune' it by sending a range of packet sizes to the target, and see which arrive. think binary_search ...
I am working on a problem in SNMP extension agent in windows, which is passing traps to snmp.exe via SnmpExtensionTrap callback.
We added a couple of fields to the agent recently, and I am starting to see that some traps are getting lost. When I intercept the call in debugger and reduce the length of some strings, the same traps, that would have been lost, will go through.
I cannot seem to find any references to size limit or anything on the data passed via SnmpExtensionTrap. Does anyone know of one?
I would expect the trap size to be limited by the UDP packet size, since SNMP runs over the datagram-oriented UDP protocol.
The maximum size of a UDP packet is 64Kb but you'll have to take into account the SNMP overhead plus any limitations of the transport you're running over (e.g. ethernet).