I am reimplementing an old network layer library, but using boost asio this time. Our software is tcpip dialoging with a 3rd party software. Several messages behave very well on both sides, but there is one case I misunderstand:
The 3rd party sends two messages (msg A and B) one after the other (real short timing) but I receive only a part of message A in tcp-packet 1, and the end of message A and the whole message B in tcp-packet 2. (I sniff with wireshark).
I had not thought of this case, I am wondering if it is common with tcp, and if my layer should be adaptative to that case - or should I say to the 3rd party to check what they do on their side so as I received both message in different packets.
Packets can be fragmented and arrive out-of-sequence. The TCP stack which receives them should buffer and reorder them, before presenting the data as an incoming stream to the application layer.
My problem is with message B, that I don't see because it's after the end of message one in the same packet.
You can't rely on "messages" having a one-to-one mapping to "packets": to the application, TCP (not UDP) looks like a "streaming" protocol.
An application which sends via TCP needs another way to separate messages. Sometimes that's done by marking the end of each message. For example SMTP marks the end-of-message as follows:
The transmission of the body of the mail message is initiated with a
DATA command after which it is transmitted verbatim line by line and
is terminated with an end-of-data sequence. This sequence consists of
a new-line (), a single full stop (period), followed by
another new-line. Since a message body can contain a line with just a
period as part of the text, the client sends two periods every time a
line starts with a period; correspondingly, the server replaces every
sequence of two periods at the beginning of a line with a single one.
Such escaping method is called dot-stuffing.
Alternatively, the protocol might specify a prefix at the start of each message, which will indicate the message-length in bytes.
If you're are coding the TCP stack, then you'll have access to the TCP message header: the "Data offset" field tells you how long each message is.
Yes, this is common. TCP/IP is a streaming protocol and your "logical" packet may be split across many "physical" packets, so the client is responsible for assembling the higher-level packets. Additionally, TCP/IP guarantees the proper ordering, so you don't have to worry about assembling out of order packets.
your problem has got nothing to do with TCP at all. your problem is that you expected asio to do the message parsing for you. it does not, you have to implement it.
if your messages are all the same size do an async read for that size.
if they are of different length do a async read for your header size, analyze the header and do an async read for the rest of the message according to the header.
if your messages are of variable length and the size is unknown but there is a defined end character or sequence then you have to save the remaining bytes behind that end sequence and append the next read to that remainder.
Related
Client shall be sending TCP data(SIP Message) around 5K bytes in the form of multiple segments.
What shall be the best approach at server side to re-assemble the segments.
NOTE:
1. It would be great if the approach is without packet sniffing
2. Performance also needs to be considered while addressing.
3. Implementation considerations: C, C++
We have tired to handle at sip protocal stack side but results are not so great.
So thinking if it can be handle it by implementing a Wrapper after Linux "Select Call" that re-assembles the complete Packet received on each file descriptor & perform further processing.
For SIP message you have to parse at least the SIP headers.
do recv until the value mentioned in Content-Length.
Without interpreting the Content-Length you cannot identify the actual length of the SIP message packet.
I am just starting out with network programming and I am having trouble keeping up with some of the stuff. Namely because there is a lot of auto-magic stuff going on under the hood that is hidden away from me, and I cant get my head around it all. In my current app, I take user input like so:
char buff[1024];
cout << "Enter a message:";
fgets(buff, 1024, stdin);
And i can easily send that off by essentially doing this:
sendto(m_socket, buff, size, flags, (SOCKADDR*)&addr, sizeof(addr));
The other variables (size,flags,etc) are obviously initialized and configured somewhere between the input and sendto call.
This all works fine, and the other end receives the data fine. the server does
recvfrom(m_socket, (char*)data, max, flags, (SOCKADDR*)&fromAddr, &fromLength)
and I can then just print out 'data' into the console, and it'd be my message.
So where exactly is my UDP packets header? Did i have to specify it? when i pass in some data, is the 'data' part of a standard UDP packet filled with the data i specify, and the header automatically populated for me (source IP, destination IP)? If so how do i even access it?
A lot of websites I have looked at talk about headers and what not. It seems to be this very specific thing. But I dont understand how this illusive header works.. I'd like to define my own header with things like segment number, total segments, etc. but i dont know how to go about this at all. My googleing isnt sending me in the right direction either..!
The UDP headers are not available to the application when you use the standard interfaces from the operating system (socket() with SOCK_DGRAM, sendto(), recvfrom() and such). They are automatically handled by the operating system's network stack. They are automatically added when you send the message and automatically stripped when you receive.
Depending on the operating system, there are some means you can write and manage the UDP headers directly over the IP routing layer, but that is certainly unusual, and would probably require administrative privileges.
If you want to define your own headers for your own purposes, you must do so inside the body of the message, i.e. parse and interpret what you send and receive sendto() and recvfrom(), thus creating what is called an application protocol. Networking is a layered architecture, where applications sits upon UDP or TCP, that sits upon IP that (usually) sits upon Ethernet or Wi-Fi. Each one has its own headers that is stripped when the data is handled to the above layer, and you only gets what you send on the application layer (maybe you can miss some packets or get them out of order, because UDP doesn't give you those guarantees, as TCP does).
UDP does not contain such things as headers, segment numbers and total segments. In fact, a UDP datagram contains nothing except the buffer that you sendto.
You can add extra information by including them with your message. Instead of simply putting your message in your buffer, make a larger buffer into which you put whatever "header" information you would like and then put your message afterwards.
From UDP's perspective, all it sees is data. It is up to the program on the receiving end to parse this data and realize that a certain part it is metadata and the other part of it is regular data.
You will have to define your message format such that it is easy for the receiving program to extract the "header" portion of the buffer. There are two common schemes: fixed headers and variable length headers.
If you are going for a fixed header, you assume that the first X bytes of every UDP message are metadata. You pick the X and it never changes per message. The recipient then knows to read X bytes as the header and all the rest as a message.
If you are going for a variable length header, you need to be able to tell the receiving end how long the header is for each particular message. A common scheme is that the first 4 bytes of the header contain an integer which says how long the header part of the message is. Then the receiving end reads that many bytes and interprets that as the header. Then it reads the rest of the data and interprets that as the message.
Lastly, the source IP and the destination IP are not properties of your UDP messages but rather properties of your socket. You can retrieve this information by inspecting the socket itself.
You can receive the UDP headers based the sockets you open up. You can receive the complete packet using socket(AF_PACKET,SOCK_RAW,htons(ETH_P_ALL));
If this socket is enabled for recvfrom then you receive the complete packet including your headers.
I'm currently trying to implement a (T)LV protocol to be used on top of TCP. A very early version of this protocol was built by just sending one message per send-recv pair. (i.e. send("message to transmit" -- recv(... )). This is really bad bandwidth-wise - I guess because I'm sending really small packets.
So now I am trying to switch to a LV protocol, sending several messages at once only seperated by their respective length (I am now using Protocol Buffers to serialize my data).
I now have two questions:
In python I send by doing
sock.send(struct.pack("<H", len(gtMessage.SerializeToString())))
sock.send(gtMessage.SerializeToString())
If I now put this into a loop and sent several of those messages I'd end up with my old problem, as far as I understand. Can I somehow string the string to be sent together?
In C++ I receive receive first the length of the message and then read the number of bytes indicated by the length field.
Is it better performance-wise to first read everything from TCP and then parse it, or can I read one message, then parse it and only then read the next bit from the wire?
Edit: So after doing some more research I'd rephrase the first question as:
Is
sock.send("somestring")
sock.send("somestring")
the same as
sock.send("somestring"+"somestring")
?
Doing two sends in a row may result in two actual packets going out, which is not so great. To fix this you can concatenate the two pieces yourself, or use writev (aka "gather write"), or TCP_CORK on the first send to prevent it from turning into a packet all by itself.
As for the receive side, you should receive a big block (as much as you can up to some reasonable limit, say a couple megabytes or something), and then parse it. Do not try to receive just one or two bytes for the size then do another receive after that--this is inefficient and you may still end up with "short reads" if the sent message was fragmented.
I am trying to send a message over a TCP socket at a regular interval (every second). Sometimes the full message will not be sent or two-four messages will be stacked and sent at once. I have if statements for if the return value is 0 or < 0, but those are never true. I tried the obvious approach of checking the exact return value of send() to see if less or more bytes were sent. It just returns the number that I specify in the parameter to send (which makes sense if send blocks until it sends that much), even if less bytes are sent. So is there an accurate way to say "was the right size packet sent? no? - do something"?
TCP provides a reliable stream of bytes, there's no message boundary. If you need to know the length of the message you have to build this into the protocol, eg: send every message with a 2 byte header which specifies the message length.
There's no such facility with TCP. It's up to the in-kernel network stack how to slice TCP stream into packets. Having said that you can set TCP_NODELAY option on your socket to disable Nagle algorithm.
If I am understanding you right, sometimes you send two or more packets and they are received as one on the distant end.
This is the nature of TCP/IP. You cannot guarantee the packets will arrive as distinct, just that they will arrive in order and reliably.
Not sure what platform you are using or what syntax you are using (streams, FILE objects or file descriptors; some code would clarify this) but you may need to do an explicit flush operation after you write each message to force the kernel. I generally use C-style file descriptors and it is usually sufficient to call fflush on the descriptors to make whatever I've queued up go out immediately.
If I write a server, how can I implement the receive function to get all the data sent by a specific client if I don't know how that client sends the data?
I am using a TCP/IP protocol.
If you really have no protocol defined, then all you can do is accept groups of bytes from the client as they arrive. Without a defined protocol, there is no way to know that you have received "all the bytes" that the client sent, since there is always the possibility that a network failure occurred somewhere between the client and your server during transmission, causing the last part of the stream not to arrive at the server. In that case, you would get the usual end-of-stream indication from the TCP socket (e.g. recv() returning 0, or EWOULDBLOCK if you are using non-blocking sockets), so you would know that you aren't going to receive any more data from the client (because the TCP connection is now disconnected)... but that isn't quite the same thing as knowing you have received all of the data the client meant for you receive.
Depending on your application, that might be good enough. If not, then you'll have to work out a protocol, and trust that your clients will abide by the rules of that protocol. Having the client send a header first saying how many bytes it plans to send is a good approach; or having it send some special "Okay, that's all I meant to send" indicator is also possible (although if you do it that way, you have to watch out for false positives if the special indicator could appear by chance inside the data itself)
One call to send does not equal one call to recv. Either send a header so the receiver know how much data to expect, or send some sort of sentinel value so the the receiver knows when to stop reading.
It depends on how you want to design your protocol.
ASCII protocols usually use a special character to delimit the end of the data, while binary protocols usually send the length of the data first as a fixed-size integer (both sides know this size) and then the variable-length data follows.
You can combine size with your data in one buffer and call send once. People usually use first 2 bytes for size of data in a packet. Like this,
|size N (2 bytes) | data (N bytes) |
In this case, you can contain 65535 byte-long custom data.
Since TCP does not preserve message boundary, it doesn't matter how many times you call send. You have to call receive until you get N size(2 bytes) then you can keep calling receive until you have N bytes data you sent.
UPDATE: This is just a sample to show how to check message boundary in TCP. Security/Encryption is a whole different story and it deserves a new thread. That said, do not simply copy this design. :)
TCP is stream-based, so there is no concept of a "complete message": it's given by a higher-level protocol (e.g. HTTP) or you'd have to invent it yourself. If you were free to use UDP (datagram-based), then there would be no need to do send() multiple times, or receive().
A newer SCTP protocol also supports the concept of a message natively.
With TCP, to implement messages, you have to tell the receiver the size of the message. It can be the first few bytes (commonly 2, since that allows messages up to 64K -- but you have to be careful of byte order if you may be communicating between different systems), or it can be something more complicated. HTTP, for example, has a whole set of rules by which the receiver determines the length of the message. One of them is the Content-Length HTTP header, which contains a string representing the number of bytes in the body of the message. Header-only HTTP messages are simply delimited by a blank line. As you can see, there are no easy (or standard) answers.
TCP is a stream based protocol. As such there is no concept of length of data built into TCP in the same way as there is no concept of data length for keyboard input.
It is therefore up to the higher level protocol to specify the end of the message. This can be done by including the packet length in the protocol or specifying a special end-of-message byte sequence.
For example HTTP headers are terminated by a double \r\n sequence and the length of the message body can be obtains from the Content-Length header.