94

I just came across this strange thing I got to see application is that by default they use SOCK_STREAM function. Why is it so? Is this SOCK_STREAM just creating multiple streams? Or is it the standard SOCK_STREAM function available for creating TCP stream(s)?

I thought tsunami is based on UDP, but still having some features like that of TCP, e.g. TCP fairness, friendlyness, etc.

Could somebody please shed some light on this issue? I am totally confused over this.

Ian Boyd
  • 246,734
  • 253
  • 869
  • 1,219
echo9
  • 1,159
  • 1
  • 13
  • 15
  • 2
    They are not functions, they are manifest constants to be provided to the `socket()` system call in accordance with its documentation. – user207421 Apr 06 '21 at 11:24
  • Related: [when is `IPPROTO_UDP` required?](https://stackoverflow.com/q/1955198/4561887) and [`IPPROTO_IP` vs `IPPROTO_TCP`/`IPPROTO_UDP`](https://stackoverflow.com/q/5385312/4561887) – Gabriel Staples Mar 10 '22 at 04:38

5 Answers5

117

TCP almost always uses SOCK_STREAM and UDP uses SOCK_DGRAM.

TCP (SOCK_STREAM) is a connection-based protocol. The connection is established and the two parties have a conversation until the connection is terminated by one of the parties or by a network error.

UDP (SOCK_DGRAM) is a datagram-based protocol. You send one datagram and get one reply and then the connection terminates.

  • If you send multiple packets, TCP promises to deliver them in order. UDP does not, so the receiver needs to check them, if the order matters.

  • If a TCP packet is lost, the sender can tell. Not so for UDP.

  • UDP datagrams are limited in size, from memory I think it is 512 bytes. TCP can send much bigger lumps than that.

  • TCP is a bit more robust and makes more checks. UDP is a shade lighter weight (less computer and network stress).

Choose the protocol appropriate for how you want to interact with the other computer.

pevik
  • 4,523
  • 3
  • 33
  • 44
Michael J
  • 7,631
  • 2
  • 24
  • 30
  • I use an IP stack from EMBOS. I created a socket of type SOCK_DGRAM. But the select function is getting invoked only the very first time when I recieve a UDP packet....Is there something to do with the socket type in this case? – Ginu Jacob Dec 04 '14 at 08:15
  • @GinuJacob - I don't know anything about EMBOS. Create a new question and select tags (such as "EMBOS") that will attract people with the right skills to help you. – Michael J Dec 05 '14 at 03:09
  • 3
    UDP/SOCK_DGRAM is a datagram-based protocol, that involves NO connection. You send any number of datagrams and receive any number of datagrams. It's an "unreliable service". – Jeff Learman Nov 19 '15 at 20:17
  • 2
    TCP/SOCK_STREAM is a "reliable" or "confirmed" service, in that packets are delivered, in order, or the connection terminates. The guarantee is that you get notified if the data might not have been delivered. – Jeff Learman Nov 19 '15 at 20:20
  • What do you mean 'almost'? When *doesn't* TCP use SOCK_STREAM? You go on to imply that they are synonyrmous. You need to clarify. The sender cannot tell whether a TCP packet is lost other than via a connection reset. And there is no connection at all in UDP, or any necessary reply, let alone a connection termination after exactly one send and one response. Answer is largely nonsense. – user207421 Apr 06 '21 at 11:27
  • 1
    @JeffLearman Not true actually, UDP is only limited (as a protocol) to 2^16 bytes. You can send very large UDP packets using IP fragmentation regardless of the MTU and the kernel will reassemble them for you – Allison May 23 '21 at 08:14
  • @Allison Of course you're right. No idea what got in my head when I wrote that. deleted my comment. Thanks. – Jeff Learman May 24 '21 at 11:36
  • 1
    UDP packets are not limited to 512 bytes. They're limited by UDP to 64K bytes. They're also limited to the max service data unit size of the network layer. For IPv4 with fragmentation enabled, this is nearly 64KB. For IPv4 with fragmentation disabled or IPv6, one should use MTU path discovery, especially if using IP packets larger than 1500 bytes. – Jeff Learman May 24 '21 at 11:42
74

One of the ideas behind the Berkley Sockets API was that it could use different protocol families - not just the Internet Protocol (IP). But instead you had one API that could handle all kinds of "address families", e.g.:

  • Internet Protocol version 4 (IPv4): AF_INET
  • IPX/SPX: AF_IPX
  • AppleTalk: AF_APPLETALK
  • NetBIOS: AF_NETBIOS
  • Internet Protocol version 6 (IPv6): AF_INET6
  • Infrared Data Association (IrDA): AF_IRDA
  • Bluetooth: AF_BTH

Each protocol family generally has a few similar concepts of how data will be handled on a socket:

  • sequenced, reliable, two-way, connection-based, byte-streams: SOCK_STREAM (what an IP person would call TCP)
  • connectionless, unreliable, datagrams: SOCK_DGRAM (what an IP person would call UDP)

Different address families have different terms for these basic concepts:

╔═══════════╦══════════════════════════╗
║           ║       Socket Type        ║
║ Address   ╟────────────┬─────────────╢
║ Family    ║ SOCK_DGRAM │ SOCK_STREAM ║ 
╠═══════════╬════════════╪═════════════╣
║ IPX/SPX   ║ SPX        │ IPX         ║
║ NetBIOS   ║ NetBIOS    │ n/a         ║
║ IPv4      ║ UDP        │ TCP         ║
║ AppleTalk ║ DDP        │ ADSP        ║
║ IPv6      ║ UDP        │ TCP         ║
║ IrDA      ║ IrLMP      │ IrTTP       ║
║ Bluetooth ║ ?          │ RFCOMM      ║
╚═══════════╩════════════╧═════════════╝

The point is:

  • If you want reliable, two-way, connection-based, sequenced, byte-streams
  • you ask for it using "SOCK_STREAM"
  • and the sockets API will worry about figuring out that you want TCP

Similarly, if i were creating a socket over Infrared (IrDA, AF_IRDA):

  • i have no idea what protocol in IrDA is reliable, sequenced, and connection-based
  • all i know is that i want something that is reliable, sequence, and connection-based

So you say:

socket(AF_IRDA, SOCK_STREAM, 0);

And Sockets will figure it out for me.

Bonus

Originally there was only the two protocol options:

  • connectionless, unreliable, datagrams (SOCK_DGRAM)
  • connection-based, reliable, sequenced, two-way (SOCK_STREAM)

Later other protocol choices were added:

  • a reliable message datagram (SOCK_RDM - "Reliable Datagram Multicast" - obsolete; do not use in new programs)
  • pseudo-stream sequenced packets based on datagrams (SOCK_SEQPACKET)
╔═══════════╦══════════════════════════════════════════════════════╗
║           ║                      Socket Type                     ║
║ Address   ╟────────────┬─────────────┬──────────┬────────────────╢
║ Family    ║ SOCK_DGRAM │ SOCK_STREAM │ SOCK_RDM │ SOCK_SEQPACKET ║ 
╠═══════════╬════════════╪═════════════╪══════════╪════════════════╣
║ IPX/SPX   ║ SPX        │ IPX         │ ?        │ ?              ║
║ NetBIOS   ║ NetBIOS    │ n/a         │ ?        │ ?              ║
║ IPv4      ║ UDP        │ TCP         │ ?        │ SCTP           ║
║ AppleTalk ║ DDP        │ ADSP        │ ?        │ ?              ║
║ IPv6      ║ UDP        │ TCP         │ ?        │ SCTP           ║
║ IrDA      ║ IrLMP      │ IrTTP       │ ?        │ ?              ║
║ Bluetooth ║ ?          │ RFCOMM      │ ?        │ ?              ║
╚═══════════╩════════════╧═════════════╧══════════╧════════════════╝

It's not guaranteed that any given address family will support such protocol choices; but some do.

Bonus Bonus Chatter

Hopefully now you see why it is redundant to pass IPPROTO_TCP protocol in your call to create a socket:

socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // passing IPPROTO_TCP is redundant
socket(AF_INET, SOCK_STREAM, 0);           // better

You already said you wanted a SOCK_STREAM. You don't need to force TCP on top of it. In the same way it's redundant to call:

socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); //passing IPPROTO_UDP is redundant
socket(AF_INET, SOCK_DGRAM, 0);           // better

tl;dr: It's a protocol-independent way of asking for TCP or UDP. But since nobody on the planet uses AppleTalk, IPX/SPX, IrDA, Bluetooth, NetBIOS anymore, it's mostly vestigial.

Mecki
  • 125,244
  • 33
  • 244
  • 253
Ian Boyd
  • 246,734
  • 253
  • 869
  • 1,219
  • 4
    I see no reason why this should not be the most accepted answer – Adam Sperry Jul 13 '20 at 22:05
  • @ArkestMust Your comment lacks relevance. TCP spans the globe. Bluetooth spans about 100 feet. In any case Bluetooth is a media layer and TCP is a session-layer protocol. There is simply no comparison. – user207421 Apr 06 '21 at 11:29
  • "*the sockets API will worry about figuring out that you want TCP*" - only when the `protocol` parameter is `0`, ie "use the default `protocol` for the specified `type`". TCP is the default protocol for `SOCK_STREAM`. But you can also specify `IPPROTO_TCP` (6) explicitly instead. Same goes with UDP, which is the default `protocol` for `SOCK_DGRAM` (`IPPROTO_UDP=22`). – Remy Lebeau Mar 10 '22 at 01:54
  • @RemyLebeau What were you workin on that brought you here this evening? – Ian Boyd Mar 10 '22 at 02:41
  • @IanBoyd what is that supposed to mean? – Remy Lebeau Mar 10 '22 at 19:03
  • @RemyLebeau My answer has been up for a few years now. And i saw your comment 45 minutes after you posted it. And it was in the evening. So i'm curious what got you stumbling across my 2 year old answer on a 10 year old question. Doing some raw socket work? It's genuine curiosity - since we we're both around here a lot. – Ian Boyd Mar 11 '22 at 00:15
  • @IanBoyd your answer may be 2 years old, but [Gabriel's answer](https://stackoverflow.com/a/71417876/65863) is only 1 day old. That triggered this question to show up on my feed, so I made some comments on his answer. And then I saw your answer, and made some more comments. – Remy Lebeau Mar 11 '22 at 00:21
8

Update: my answer seems no more relevant, but the original question referred to UDT, which is a connection-oriented protocol built on top of UDP. More info here: http://en.wikipedia.org/wiki/UDP-based_Data_Transfer_Protocol


UDT appears to provide API which mimics classic BSD sockets API, so it can be used as a drop-in replacement, for both stream and datagram oriented applications. Check e.g. sendmsg and recvmsg - both throw an exception if used on a socket created with SOCK_STREAM, and all the stream oriented APIs throw an exception for socket created with SOCK_DGRAM as well.

In case of SOCK_DGRAM it perform some extra processing however, it doesn't simply wrap the UDP socket transparently in such case - as far as I understand the code after a quick review (I'm not familiar with UDT internals or protocol spec). Reading the technical papers could help a lot.

The library always creates its underlying, "real" socket as a datagram one (check channel.cpp, CChannel::open).

Code Painters
  • 7,175
  • 2
  • 31
  • 47
1

Preface: useful macros

Here are some useful macros from my go-to socket demo files I wrote for myself, which make it clear how to get UDP vs TCP packets.

From these files:

  1. socket__geeksforgeeks_udp_server_GS_edit_GREAT.c
  2. socket__geeksforgeeks_udp_client_GS_edit_GREAT.c

...you can find these macros:

// See: https://linux.die.net/man/7/ip
// AF = "Address Family"
// INET = "Internet"
// AF_INET = IPv4 internet protocols
// AF_INET6 = IPv6 internet protocols; see: https://linux.die.net/man/2/socket
// DGRAM = "Datagram" (UDP)
//
// IPv4
#define SOCKET_TYPE_TCP_IPV4              AF_INET, SOCK_STREAM, 0
#define SOCKET_TYPE_UDP_IPV4              AF_INET, SOCK_DGRAM, 0
#define SOCKET_TYPE_RAW_IPV4(protocol)    AF_INET, SOCK_RAW, (protocol)
// IPv6
#define SOCKET_TYPE_TCP_IPV6              AF_INET6, SOCK_STREAM, 0
#define SOCKET_TYPE_UDP_IPV6              AF_INET6, SOCK_DGRAM, 0
#define SOCKET_TYPE_RAW_IPV6(protocol)    AF_INET6, SOCK_RAW, (protocol)

Usage examples:

int socket_tcp = socket(SOCKET_TYPE_TCP_IPV4);
int socket_udp = socket(SOCKET_TYPE_UDP_IPV4);
// See also: https://www.binarytides.com/raw-sockets-c-code-linux/
int socket_raw = socket(SOCKET_TYPE_RAW_IPV4(IPPROTO_RAW));

Now back to the question:

What is SOCK_DGRAM and SOCK_STREAM?

Brief Summary

UDP --(is the protocol utilized by)--> AF_INET, SOCK_DGRAM or AF_INET6, SOCK_DGRAM
TCP --(is the protocol utilized by)--> AF_INET, SOCK_STREAM or AF_INET6, SOCK_STREAM

Examples: from https://linux.die.net/man/7/ip (or as shown in your terminal man pages by running man 7 ip):

tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
raw_socket = socket(AF_INET, SOCK_RAW, protocol);

Long Summary

Reference the int socket(AddressFamily, Type, Protocol) socket creation function documentation here and here (can also be viewed by running man 2 socket). It allows you to specify these 3 parameters:

  1. Address Family
  2. Socket Type
  3. Protocol

For many if not most use-cases, however, the most-useful options for these parameters are frequently:

  1. Address Family: AF_INET (for IPv4 addresses) or AF_INET6 (for IPv6 addresses).

  2. Socket Type: SOCK_DGRAM or SOCK_STREAM.

  3. Protocol: just use 0 to allow it to use default protocols, as specified from the documentation link above (emphasis added):

    Protocol: Specifies a particular protocol to be used with the socket. Specifying the Protocol parameter of 0 causes the socket subroutine to default to the typical protocol for the requested type of returned socket.

  4. SOCK_DGRAM: if you create your socket with AF_INET as

    int s = socket(AF_INET, SOCK_DGRAM, 0)
    

    or with AF_INET6 as

    int s = socket(AF_INET6, SOCK_DGRAM, 0)
    

    ...the socket utilizes the UDP protocol by default when the (AF_INET or AF_INET6) address family and SOCK_DGRAM Socket Types are selected.

    1. In the UNIX Address Family domain (AF_UNIX): when communicating between processes running on the same operating system via the AF_UNIX Address Family, this is similar to an inter-process message queue.
    2. In the Internet Address Family domain (AF_INET and AF_INET6): when communicating between a local process and a process running on a remote host via the AF_INET Address Family, this is "implemented on the User Datagram Protocol/Internet Protocol (UDP/IP) protocol."
  5. SOCK_STREAM: if you create your socket with AF_INET as

    int s = socket(AF_INET, SOCK_STREAM, 0)
    

    or with AF_INET6 as

    int s = socket(AF_INET6, SOCK_STREAM, 0)
    

    ...the socket utilizes the TCP protocol by default when the (AF_INET or AF_INET6) address family and SOCK_STREAM Socket Types are selected.

    1. In the UNIX Address Family domain (AF_UNIX): when communicating between processes running on the same operating system via the AF_UNIX Address Family, this type of socket "works like a pipe" IPC (Inter-process Communication) mechanism.
    2. In the Internet Address Family domain (AF_INET and AF_INET6): when communicating between a local process and a process running on a remote host via the AF_INET Address Family, this is "implemented on the Transmission Control Protocol/Internet Protocol (TCP/IP) protocol."

Details

In the explanation below, wherever I (or they, in the quoted sections) use AF_INET (for IPv4 addresses), keep in mind you can also use AF_INET6 (for IPv6 addresses) if you like.

In socket-based communication, including for sending both UDP/IP and TCP/IP Ethernet data packets back and forth between two running processes on the same computer, or between two separate computers, you must specify both the Address Family (these constants begin with AF_) and Socket Type (these constans begin with SOCK_).

The best documentation I have found on sockets, hands-down, is from IBM.com, such as here:

  1. int socket(AddressFamily, Type, Protocol) function: https://www.ibm.com/docs/en/aix/7.1?topic=s-socket-subroutine
  2. Address Families: https://www.ibm.com/docs/en/aix/7.1?topic=domains-address-families and here
  3. Socket Types: https://www.ibm.com/docs/en/aix/7.1?topic=protocols-socket-types

For additional information on "Sockets", click the links in the left-hand navigation pane after clicking one of the links above.

Other excellent documentation can also be found on linux.die.net, such as the ip(7) page here.

Address Family (AF_) Domains

From the "Address Families" link above, first, we learn about the various socket Address Families (AF) domains, which are a prerequisite to understanding the socket types. Here is that information (emphasis added, and my notes added in square brackets []):

A socket subroutine that takes an address family (AF) as a parameter can use AF_UNIX (UNIX), AF_INET (Internet), AF_NS (Xerox Network Systems), or AF_NDD (Network Device Drivers of the operating sytem) protocol. These address families are part of the following communication domains:

UNIX: Provides socket communication between processes running on the same operating system when an address family of AF_UNIX is specified. A socket name in the UNIX domain is a string of ASCII characters whose maximum length depends on the machine in use.

Internet: Provides socket communication between a local process and a process running on a remote host when an address family of AF_INET is specified. The Internet domain requires that Transmission Control Protocol/Internet Protocol (TCP/IP) be installed on your system. A socket name in the Internet domain is an Internet address, made up of a 32-bit IP address [ex: 192.168.0.1] and a 16-bit port address [any number from 0 to 65535; here is a list of common TCP and UDP port numbers].

NDD: Provides socket communication between a local process and a process running on a remote host when an address family of AF_NDD is specified. The NDD domain enables applications to run directly on top of physical networks. This is in contrast to the Internet domain, in which applications run on top of transport protocols such as TCP, or User Datagram Protocol (UDP). A socket name in the NDD domain consists of operating system NDD name and a second part that is protocol dependent.

Communication domains [ex: AF_UNIX or AF_INET] are described by a domain data structure that is loadable. Communication protocols [ex: SOCK_DGRAM (UDP) or SOCK_STREAM (TCP)] within a domain are described by a structure that is defined within the system for each protocol implementation configured. When a request is made to create a socket, the system uses the name of the communication domain to search linearly the list of configured domains. If the domain is found, the domain's table of supported protocols is consulted for a protocol appropriate for the type of socket being created or for a specific protocol request. (A wildcard entry may exist for a raw domain.) Should multiple protocol entries satisfy the request, the first is selected.

Socket Types (SOCK_)

From the "Socket Types" link above, we learn about the various "underlying communication protocols" (emphasis added, and my notes added in square brackets []):

Sockets are classified according to communication properties. Processes usually communicate between sockets of the same type. However, if the underlying communication protocols support the communication, sockets of different types can communicate.

Each socket has an associated type, which describes the semantics of communications using that socket. The socket type determines the socket communication properties such as reliability, ordering, and prevention of duplication of messages. The basic set of socket types is defined in the sys/socket.h file:

/*Standard socket types */
#define  SOCK_STREAM             1 /*virtual circuit*/
#define  SOCK_DGRAM              2 /*datagram*/
#define  SOCK_RAW                3 /*raw socket*/
#define  SOCK_RDM                4 /*reliably-delivered message*/
#define  SOCK_CONN_DGRAM         5 /*connection datagram*/

Other socket types can be defined.

The operating system supports the following basic set of sockets:


SOCK_DGRAM: Provides datagrams, which are connectionless messages of a fixed maximum length. This type of socket is generally used for short messages, such as a name server or time server, because the order and reliability of message delivery is not guaranteed.

In the UNIX domain [AF_UNIX], the SOCK_DGRAM socket type is similar to a message queue. In the Internet domain [AF_INET], the SOCK_DGRAM socket type is implemented on the User Datagram Protocol/Internet Protocol (UDP/IP) protocol.

A datagram socket supports the bidirectional flow of data, which is not sequenced, reliable, or unduplicated. A process receiving messages on a datagram socket may find messages duplicated or in an order different than the order sent. Record boundaries in data, however, are preserved. Datagram sockets closely model the facilities found in many contemporary packet-switched networks.

SOCK_STREAM: Provides sequenced, two-way byte streams with a transmission mechanism for stream data. This socket type transmits data on a reliable basis, in order, and with out-of-band capabilities.

In the UNIX domain [AF_UNIX], the SOCK_STREAM socket type works like a pipe. In the Internet domain [AF_INET], the SOCK_STREAM socket type is implemented on the Transmission Control Protocol/Internet Protocol (TCP/IP) protocol.

A stream socket provides for the bidirectional, reliable, sequenced, and unduplicated flow of data without record boundaries. Aside from the bidirectionality of data flow, a pair of connected stream sockets provides an interface nearly identical to pipes.

SOCK_RAW: Provides access to internal network protocols and interfaces. This type of socket is available only to users with root-user authority, or to non-root users who have the CAP_NUMA_ATTACH capability. (For non-root raw socket access, the chuser command assigns the CAP_NUMA_ATTACH capability, along with CAP_PROPAGATE. For further information, refer to the chuser command.)

Raw sockets allow an application to have direct access to lower-level communication protocols. Raw sockets are intended for advanced users who want to take advantage of some protocol feature that is not directly accessible through a normal interface, or who want to build new protocols on top of existing low-level protocols.

Raw sockets are normally datagram-oriented, though their exact characteristics are dependent on the interface provided by the protocol.

SOCK_SEQPACKET: Provides sequenced, reliable, and unduplicated flow of information.

SOCK_CONN_DGRAM: Provides connection-oriented datagram service. This type of socket supports the bidirectional flow of data, which is sequenced and unduplicated, but is not reliable. Because this is a connection-oriented service, the socket must be connected prior to data transfer. Currently, only the Asynchronous Transfer Mode (ATM) protocol in the Network Device Driver (NDD) domain supports this socket type.

How do they work?

The SOCK_DGRAM and SOCK_RAW socket types allow an application program to send datagrams to correspondents named in send subroutines. Application programs can receive datagrams through sockets using the recv subroutines. The Protocol parameter is important when using the SOCK_RAW socket type to communicate with low-level protocols or hardware interfaces. The application program must specify the address family in which the communication takes place.

This is the general sequence of function calls required to communicate using SOCK_STREAM (TCP protocol) socket types:

The SOCK_STREAM socket types are full-duplex byte streams. A stream socket must be connected before any data can be sent or received on it. When using a stream socket for data transfer, an application program needs to perform the following sequence:

  1. Create a connection to another socket with the connect subroutine.
  2. Use the read and write subroutines or the send and recv subroutines to transfer data.
  3. Use the close subroutine to finish the session.

An application program can use the send and recv subroutines to manage out-of-band data.

Possible errors returned or set in the errno variable when using SOCK_STREAM:

SOCK_STREAM communication protocols are designed to prevent the loss or duplication of data. If a piece of data for which the peer protocol has buffer space cannot be successfully transmitted within a reasonable period of time, the connection is broken. When this occurs, the socket subroutine indicates an error with a return value of -1 and the errno global variable is set to ETIMEDOUT. If a process sends on a broken stream, a SIGPIPE signal is raised. Processes that cannot handle the signal terminate. When out-of-band data arrives on a socket, a SIGURG signal is sent to the process group.

The process group associated with a socket can be read or set by either the SIOCGPGRP or SIOCSPGRP ioctl operation. To receive a signal on any data, use both the SIOCSPGRP and FIOASYNC ioctl operations. These operations are defined in the sys/ioctl.h file.

That about covers it. I hope to write some basic demos in my eRCaGuy_hello_world repo in the c dir soon.

Main References:

  1. [my answer] What does the number in parentheses shown after Unix command names in manpages mean?
  2. *****https://linux.die.net/man/7/ip
  3. https://linux.die.net/man/2/socket
  4. https://linux.die.net/man/7/tcp
  5. https://linux.die.net/man/7/udp
  6. int socket(AddressFamily, Type, Protocol) function: https://www.ibm.com/docs/en/aix/7.1?topic=s-socket-subroutine
  7. Address Families: https://www.ibm.com/docs/en/aix/7.1?topic=domains-address-families and here
  8. Socket Types: https://www.ibm.com/docs/en/aix/7.1?topic=protocols-socket-types

Related:

  1. What is SOCK_DGRAM and SOCK_STREAM?
  2. when is IPPROTO_UDP required?
  3. IPPROTO_IP vs IPPROTO_TCP/IPPROTO_UDP
Gabriel Staples
  • 36,492
  • 15
  • 194
  • 265
  • 3
    "*`SOCK_DGRAM` is UDP... `SOCK_STREAM` is TCP*" - that is incorrect on both counts. `SOCK_DGRAM` is a datagram-oriented socket, regardless of the transport protocol used. UDP is one, but not the only, transport that uses datagrams. `SOCK_STREAM` is a stream-oriented socket, regardless of the transport protocol used. TCP is one, but not the only, transport that uses streams. The `protocol` parameter of `socket()` dictates whether UDP/TCP is used, not the `type` parameter. But UDP can only be used on a `SOCK_DGRAM` type socket, and TCP can only be used on a `SOCK_STREAM` type socket. – Remy Lebeau Mar 10 '22 at 01:42
  • @RemyLebeau, what if I change it to: "`SOCK_DGRAM` utilizes the UDP protocol when the `AF_INET` address family domain is selected"? – Gabriel Staples Mar 10 '22 at 01:44
  • 1
    That would also be incorrect, since UDP and TCP both also support `AF_INET6`. The address family dictates how peers are addressed (IPv4 vs IPv6 vs ...), not related to the type of the socket (datagram vs stream vs ...), or the protocol used (UDP vs TCP vs ...). UDP is used only when the socket protocol is explicitly `IPPROTO_UDP`. TCP is used only when the socket protocol is explicitly `IPPROTO_TCP`. Other transports are possible (ICMP, IPX, RAW, etc). – Remy Lebeau Mar 10 '22 at 01:45
  • @RemyLebeau, let me work on it. I'm new to `socket`s. Lots to absorb here. – Gabriel Staples Mar 10 '22 at 01:50
  • @RemyLebeau, I'm really trying to get this right. How about now? – Gabriel Staples Mar 10 '22 at 01:59
  • 1
    It is still a bit misleading. You really need to differentiate between the *type* of the socket, and the *protocol* the socket uses. `socket()` makes that distinction. Your explain doesn't, not very well anyway. And you are still completely ignoring that `AF_INET6` exists for IPv6 addressing. `AF_INET` is for IPv4 addressing. – Remy Lebeau Mar 10 '22 at 02:04
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/242791/discussion-between-gabriel-staples-and-remy-lebeau). – Gabriel Staples Mar 10 '22 at 02:28
  • @RemyLebeau, I updated the answer a bunch again, FYI, per your comments. – Gabriel Staples Mar 21 '22 at 02:30
  • 1
    "TCP is a default protocol utilized by `SOCK_STREAM`" is nonsensical. `SOCK_STREAM` is just a selector constant for an API. The API has no notion of "default for `SOCK_STREAM` or `SOCK_DGRAM`". Maybe in case of `AF_X` + `SOCK_Y` you could speak in terms of defaults, but that misses the point of the question. – Błażej Michalik Jun 02 '22 at 18:28
  • @BłażejMichalik, I feel like this is a case of pedantic people arguing about both English semantics and Berkely sockets API semantics simultaneously. Perhaps "de facto standad" is a more-appropriate term than "default", to a pedantic, since no notion of "default" exists in the Berkely sockets contract, but rather only exists in the implementation of it?--all of which use the defaults as I stated in my brief summary? Anyway, I'm not sure what else to say about this other than I feel it is a case of pedantics arguing about pedantry. – Gabriel Staples Jun 02 '22 at 18:36
  • 1
    No, because the point of these selectors is that the API makes the choice based on `AF`/`SOCK` matrix. Saying "it's a default for `SOCK_XYZ`" perpetuates a fallacious idea, that there is a default for a `SOCK_*` in the absence of `AF_*`. – Błażej Michalik Jun 03 '22 at 03:29
  • @BłażejMichalik, I updated the top of my answer. I see that address family `AF_*` and `SOCK_*` must be bound as a pair. I've never seen anything used in the first parameter _other than_ `AF_INET` or `AF_INET6`, but my socket experience is limited, and I get the impression that this interface was developed when the industry standards were still very much in-flux and evolving, and eventually the industry settled on the common usages we see today. – Gabriel Staples Jun 03 '22 at 03:47
-6

TCP uses SOCK_STREAM and UDP uses SOCK_DGRAM.