I am trying to send a packet using UDP. I know that if the channel is not free the packet will not be sent. I am using QT's udpSocket->writeDatagram to send a UDP packet. I am doing it in a loop, I want to make sure I do not send another packet before the previous packet has been sent. Is there a flag, or any other way that I can check and make sure the packet is sent?
UDP is an unreliable protocol by design. It does not guarantee that packets don't get lost, and when they get lost, the sender is not informed about that. So you can never know if a UDP packet was received successfully by the other side.
Unless, of course, your application level protocol sends a certain response. But the response can get lost just as easily, so no response is no definite proof that the packet wasn't received.
The docs say:
Sends the datagram at data of size size to the host address address at
port port. Returns the number of bytes sent on success; otherwise
returns -1.
So if it returns something other than -1 you can consider it "sent". However, if what you really want to know is whether it made it to the other side, you'll want to hear from the peer.
Typically in order to send UDP packets as fast as possible (but no faster), you'll want to put the socket into non-blocking mode, then send packets in a loop until send()/sendto() returns -1/EAGAIN (aka EWOULDBLOCK). When that result-code is returned, break out of your send-loop loop and wait for the socket to become writable again. Under Qt, you can set up a QSocketNotifier object (once, right after you set up your socket) and it will emit an activated(int) signal whenever your socket has space for more outgoing data. When you receive that signal, you can send some more packets.
Related
I've created a packet socket
m_socket = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
and attached a TX ring buffer. I fill out ethernet, ip and udp headers correctly and things work out great until the source and destination MACs happen to be equal. Then netcat (or any other utility/udp receivers) fails to receive the packet I sent. The packet is being sent according to tcpdump though.
I read somewhere that any network device would simply just ignore packets like this, but I still see this behavior on the loopback interface (why doesn't it loop back in this case?).
I only control the sender and due to performance reasons this is the way to go. However, one of the recipients may be located on the same computer and in this case either lo or eth0 will be used (depends on configuration).
How can I force the interface to not ignore these packets?
EDIT:
Using a raw packet socket socket for receiving shows that I do get both outgoing (PACKET_OUTGOING) and incomming (PACKET_HOST). However, using a more 'regular' UDP socket for receiving does not catch anything at all.
This seems to be to some odd behavior with raw sockets. See this related ticket on stackoverflow.
I have a client application using winsock's sendto() method to send data to a server application with UDP. On my client application I make, say, 5 quick sendto(). On my server application, I wait for, say, 10 secs, and then do a select() and recvfrom(). Will the recvfrom() give me the first packet sent by the client or will it be an arbitrary one (whichever one arrived first)? Will I still be able to get the other 4 data packets or does winsock's UDP framework only buffer one?
Will the recvfrom() give me the first packet sent by the client or
will it be an arbitrary one
Since UDP doesn't handle reordering, you can get any of the messages. You could get less than 4 messages or even more (but that's rare today).
UDP gives no guarantee to the received ordering of packets, so basically, the first packet you recvfrom() might be the first packet you sent, but must not be - that's what TCP is for (which guarantees ordering of received data). You might not receive a part of the packets (or any, for that matter) at all if they were lost in transit.
For the second part: generally, the operating system will buffer a certain amount of packets for you, this depends on the socket buffer set up for UDP sockets - the buffer is specific to every socket, and not shared between them. On Windows, I'm not sure at how to get at the size of the buffer, on Linux, check out "/proc/sys/net/ipv4/udp_mem"; generally, you'll easily fit five UDP packets in there.
With 5 packets of reasonable size, you will probably get all of the packets and you will probably get the first one sent first. But they might be out of order, might not arrive, and might not contain the original data if they do arrive. You have to handle all of that yourself with UDP. (But depending on your application and requirements and the stability of your network, it might not be a real problem; it is certainly possible for certain situations to exist where receiving 99% of the data is perfectly fine).
I have a tcp socket on which I receive video stream. I want to receive data as packet by packet from socket so that I could remove the packet header and keep the only stream data. How can I do this??
any help will be appreciated.
You can't. TCP doesn't work with packets / messages etc. TCP works with bytes. You get a stream of bytes. The problem is that there's no guarantee reagarding the number of bytes you'll get each time you read from a socket. The usual way to handle this:
When you want to send a "packet" include as the first thing a length
When you read stuff from a socket make sure you read at least that length
Your message could be:
|Message Length:4bytes|Additional header Information:whatever1|Message Data:whatever2|
What you'll then have to do is read 4 bytes and then read as much as those 4 bytes tell you. Then you'll be able to strip the header and get the data.
As others have mentioned, TCP is a streaming protocol. This means from an API point of view, there is no concept of "packet". As a user, all you can expect is a stream of data.
Internally, TCP will break the stream into segments that can be placed into IP packets. These packets will be sent along with control data, over IP, to the remote end. The remote end will receive these IP packets. It may discard certain IP packets (in the case of duplicates), reorder the packets or withhold data until earlier packets have arrived. All this is internal to TCP meaning the concept of a "TCP packet" is meaningless.
You might be able to use raw sockets to receive the raw IP packets but this will mean you will have to reimplement much of the TCP stack (like sending ACKs and adjusting window size) to get the remote end to perform correctly. You do not want to do this.
UDP, on the other hand, is a datagram protocol. This means that the user is made aware of how the data is sent over the network. If the concept of packets or datagrams are important to you, you will need to build your own protocol on top of UDP.
TCP is a stream protocol and it doesn't guaranty that when you call socket read function you will receive one, complete packet. UDP or SCTP are packet oriented protocols and guaranty this. For TCP you can get part of the packet or few packet at once. You have to build your own application protocol on top of TCP and fragment/defragment messages manually.
TCP is a streaming protocol. You get bytes with no message boundaries. The solution is to buffer all your reads and extract/process full video packets from the buffer.
Algorithm:
Initialize an empty buffer.
Examine buffer for a complete packet.
If found, remove complete packet from beginning of buffer and process it.
If not found, append data from a recv() to the buffer and go to #2.
What a "complete packet" contains should be defined by the video streaming protocol.
Are you pretty sure about this approach? In my opinion these "preprocessing" will introduce an additional overhead to the system. And of course this is handled by a lower layer (Read about OSI model) so it is not easy to change. Note that most of the existing streaming protocols are already optimized for the best performance.
Does recv() call intercepts data in packets or can i get data packets with timestamps?
On a datagram socket (like UDP), recv gets data in datagrams. TCP is a stream-mode socket, however, and recv gets a collection of bytes with no regard for packets.
It's possible, using low-level APIs, to get the packets, but if you were hoping to see boundaries between send calls you are out of luck... that information is not present in the packets.
Recv gets data from a socket that has been successfully received. It does not tell you when that happened; i.e. no timestamp.
Would you elaborate on what problem you're trying to solve ("why do you need this?") instead of your attempted solution? (Or have I completely misunderstood your question?)
If your own code is sending data to the remote machine where you are receiving data...then you can make you r own application level data format...such as sending the data after sending timestamp (some specified number of bytes).
This information can be extracted at the receiving end. Although as mentioned connection is TCP ...the data would be in stream format not as a complete packet as in case of UDP.
I'm working with UDP sockets in C++ for the first time, and I'm not sure I understand how they work. I know that sendto/recvfrom and send/recv normally return the number of bytes actually sent or received. I've heard this value can be arbitrarily small (but at least 1), and depends on how much data is in the socket's buffer (when reading) or how much free space is left in the buffer (when writing).
If sendto and recvfrom only guarantee that 1 byte will be sent or received at a time, and datagrams can be received out of order, how can any UDP protocol remain coherent? Doesn't this imply that the bytes in a message can be arbitrarily shuffled when I receive them? Is there a way to guarantee that a message gets sent or received all at once?
It's a little stronger than that. UDP does deliver a full package; the buffer size can be arbitrarily small, but it has to include all the data sent in the packet. But there's also a size limit: if you want to send a lot of data, you have to break it into packets and be able to reassemble them yourself. It's also no guaranteed delivery, so you have to check to make sure everything comes through.
But since you can implement all of TCP with UDP, it has to be possible.
usually, what you do with UDP is you make small packets that are discrete.
Metaphorically, think of UDP like sending postcards and TCP like making a phone call. When you send a postcard, you have no guarantee of delivery, so you need to do something like have an acknowledgement come back. With a phone call, you know the connection exists, and you hear the answers right away.
Actually you can send a UDP datagram of 0 bytes length. All that gets sent is the IP and UDP headers. The UDP recvfrom() on the other side will return with a length of 0. Unlike TCP this does not mean that the peer closed the connection because with UDP there is no "connection".
No. With sendto you send out packets, which can contain down to a single byte.
If you send 10 bytes as a single sendto call, these 10 bytes get sent into a single packet, which will be received coherent as you would expect.
Of course, if you decide to send those 10 bytes one by one, each of them with a sendto call, then indeed you send and receive 10 different packets (each one containing 1 byte), and they could be in arbitrary order.
It's similar to sending a book via postal service. You can package the book as a whole into a single box, or tear down every page and send each one as an individual letter. In the first case, the package is bulkier but you receive the book as a single, ordered entity. In the latter, each package is very light, but good luck reading that ;)
I have a client program that uses a blocking select (NULL timeout parameter) in a thread dedicated to waiting for incoming data on a UDP socket. Even though it is blocking, the select would sometimes return with an indication that the single read descriptor was "ready". A subsequent recvfrom returned 0.
After some experimentation, I have found that on Windows at least, sending a UDP packet to a port on a host that's not expecting it can result in a subsequent recvfrom getting 0 bytes. I suspect some kind of rejection notice might be coming from the other end. I now use this as a reminder that I've forgotten to start the process on the server that looks for the client's incoming traffic.
BTW, if I instead "sendto" a valid but unused IP address, then the select does not return a ready status and blocks as expected. I've also found that blocking vs. non-blocking sockets makes no difference.