views:

217

answers:

6

In theory nothing prevents using TCP socket with SOCK_DGRAM. What you'll get is reliable datagram transport. Is this possible using Berkeley sockets?

+3  A: 

SOCK_DGRAM as the type gets you a UDP socket. You can encapsulate UDP in TCP of course, but you'd have to handle the UDP part in userspace. Whether something is reliable depends on the protocol on the wire. If you use TCP, it is reliable; UDP is not.

To create a UDP socket:

int s;
s = socket(AF_INET, SOCK_DGRAM, 0);

To create a TCP socket:

int s;
s = socket(AF_INET, SOCK_STREAM, 0);

There are two common ways to send discrete chunks of data across the wire. You can either use UDP and send a discrete chunk as a datagram, or you can but structs into TCP data, and let them go as a stream. Using TCP is generally simpler and less failure-prone. If you use UDP, just time out and keep requesting the same data until you get it.

WhirlWind
"You can encapsulate UDP in TCP of course, but you'd have to handle the UDP part in userspace." That won't make the encapsulated UDP aligned with TCP packets.
sustrik
A: 

Not really. TCP and UDP are protocols from the same layer, and they have functions that make sense only to them. Take listen() and accept() for instance.

You could send UDP header+data inside TCP packets, but doesn't make sense at all. Why would you do that? A specie of tunnelling? In fact, it's very easy to parse and build UDP packets by hand, but I don't see a real application in your scenario.

jweyrich
"You could send UDP header+data inside TCP packets" - but that won't make encapsulated UDP aligned with TCP packets. As noted above the scenario is to allow deterministic dissection of the protocol layered on top of TCP.
sustrik
Exact, it won't. IMO, there's no reason for doing that. If one wants the benefits of TCP, stick to TCP, and only that.
jweyrich
Hm. Have you ever seen how say wireshark parses protocols on top of TCP? It's pure heuristics. If the unit of the protocol isn't aligned with TCP packet it simply fails. Same for HW monitoring devices.
sustrik
I guess my previous comment wasn't clear. When I said "there's no reason for doing that", I meant encapsulating UDP into TCP, not about the alignment.
jweyrich
Why do you need to have data in separate packets to do "deterministic dissection?" Why can't you just send data in individual structures across a stream. Use a fixed length, or use the first couple bytes to mark the length if it is variable. Then deterministic dissection is easy. Lots of protocols already do that. Wireshark reconstructs the streams and shows you the contents.
WhirlWind
The other problem here is that even if you could align data inside TCP packets, it still doesn't get you what you want. If IP fragmentation occurs, your data will be broken up. If a packet is lost or corrupted, Wireshark will show out of order or incorrect results. These certainly aren't things you can control from the sender.
WhirlWind
Yes, packet fragmentation is (I guess) the major problem here, since TCP handles ordering. But you can still parse the non-fragmented packets and discard others. The checksum is your friend.
jweyrich
Not to mention, a number of ethernet cards are starting to implement things like receive-side coalescing, which will screw this all up to no end as it packs everything together before it even gets to Wireshark.
WhirlWind
@whirlwind: good observation about packet coallescing!
sustrik
You can assemble the application packets/messages. Wireshark does infact do this for a lot of protocols, it does not "simply fail" - though it does need get the start of the entire tcp stream, or the start where a packet does begin on a boundary. You'll see the 'misc' column say "segment of reassembled pdu" when wireshark reassemles the application protocol. As each protocol has its own way of specifying how long a message is, this isn't a general thing
nos
+1  A: 

In theory nothing prevents using TCP socket with SOCK_DGRAM. What you'll get is reliable datagram transport. Is this possible using Berkeley sockets?

No, Berkeley API provides unreliable datagram or reliable stream.

If you want to send reliable chunks over TCP use some protocol that splits stream into chunks. That is very simple to do.

Artyom
What I was up to was having my data aligned with TCP packets. Such an arrangement would allow monitoring tools to dissect the packets in a deterministic way.
sustrik
+1  A: 

What you want to take a look at is the SCTP Protocol. It provides the ability to send Datagrams over a reliable TCP style connection:

In contrast to TCP, SCTP may be characterized as record-oriented, meaning it transports data in terms of messages, in a similar fashion to the User Datagram Protocol (UDP), so that a group of bytes (message) sent in one transmission operation (record) is read exactly as that group at the receiver application. TCP is stream-oriented, transporting streams of bytes, which it correctly reorders in case of out-of-order delivery. It does not, however, honor message boundaries, i.e., the structure of data in terms of their original transmission units at the sender.

Take a look at SCTP one to one style connections which are probably what you're looking for.

There are implementations for most Unix / Linux OS and there is a third party implementation for Windows. See the end of the Wiki article I linked for details.

Robert S. Barnes
Sure, I know about SCTP, used it, spoke to its creators, the design they've chose was focused exactly on the problem I am speaking about (hardware friendliness). However, I wanted to do the same thing with TCP. It seems that there's no other way than reimplementing TCP or patching kernel though.
sustrik
@sustrik : So why not use SCTP if it's exactly what you need?
Robert S. Barnes
A: 

I've not seen any socket api that give you this option - and it would also defeat some of the purpose of TCP to let you control the data alignment. TCP is just the transport, and its abstraction is a byte stream.

You will have to build your own message structure on top of TCP that gives you the concept of messages that the application layer care about.

nos
A: 

You can simulate things, but there's really no reason to do so. Either you want reliable delivery or you want timely delivery. TCP gives you the first, UDP gives the second. The two can't mix because TCP implements reliability by repeatedly telling the other end about the messages until they're acknowledged. For streaming, you generally need reliable delivery of data (so you can reassemble the stream), but for small messages where order isn't important (i.e., datagrams) you don't need all that overhead (UDP does largely guarantee that messages at least won't arrive garbled; that's one of the things that both TCP and UDP offer over raw IP).

There are some other interesting cases between these two extremes, of course. For real-time streaming data (e.g., video calling), you use RTP because you're streaming but can recover from data loss better than delay. For messages that are too large for UDP (64kB is the strict upper-bound, since the UDP header only has 16 bits for its length field) you pretty-much need to use TCP for transport anyway so that you can reassemble the fragments (hence SOAP goes over HTTP over TCP, and not via UDP).

Donal Fellows