当socket()中的“类型”为SOCK_DGRAM或SOCK_STREAM时,是否需要指定“协议”?

时间:2018-08-24 02:52:56

标签: c linux sockets tcp udp

来自APUE

#include <sys/socket.h>
int socket(int domain, int type, int protocol);

位置:

  • type可以是SOCK_DGRAM, SOCK_RAW, SOCK_SEQPACKET, SOCK_STREAM,并且
  • protocol可以是IPPROTO_TCPIPPROTO_UDP,...

SOCK_DGRAM是否可以与IPPROTO_UDP一起使用,但不能与IPPROTO_TCP一起使用?

SOCK_STREAM是否可以与IPPROTO_TCP一起使用,但不能与IPPROTO_UDP一起使用?

如果答案是肯定的,是否意味着当protocoltypeSOCK_DGRAM时我们不需要指定SOCK_STREAM吗?

1 个答案:

答案 0 :(得分:2)

socket(2)的手册页中:

  

协议指定要与之配合使用的特定协议   的          插座。通常仅存在一个协议来支持特定协议          给定协议系列中的套接字类型,在这种情况下,协议可以          指定为0。但是,可能有许多协议          存在,在这种情况下,必须在此指定特定协议          方式。使用的协议号特定于“通信”          进行通讯的领域”;参见协议(5)。看到          getprotoent(3)关于如何将协议名称字符串映射到协议编号。

因此是否需要指定协议字段取决于 type 字段。假设域为AF_INET,即IPv4,则SOCK_DGRAMSOCK_STREAM的协议字段都应设置为0。 ip(7)的手册页显示如下:

  

简介

   #include <sys/socket.h>
   #include <netinet/in.h>
   #include <netinet/ip.h> /* superset of previous */

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

...

     

通过调用socket(2)函数创建IP套接字   作为套接字(AF_INET,套接字类型,协议)。有效插座   类型为SOCK_STREAM以打开tcp(7)套接字,SOCK_DGRAM   打开udp(7)套接字,或SOCK_RAW打开raw(7)套接字   直接访问IP协议。 protocol是IP协议中的   要接收或发送的IP标头。 的唯一有效值   TCP通讯协定的通讯协定为0和IPPROTO_TCP,而0和   用于UDP套接字的IPPROTO_UDP。对于SOCK_RAW,您可以指定一个有效的   RFC 1700分配编号中定义的IANA IP协议。

ipv6(7)手册页显示了一些不同的内容:

  

简介

   #include <sys/socket.h>
   #include <netinet/in.h>

   tcp6_socket = socket(AF_INET6, SOCK_STREAM, 0);
   raw6_socket = socket(AF_INET6, SOCK_RAW, protocol);
   udp6_socket = socket(AF_INET6, SOCK_DGRAM, protocol);

尽管手册页没有说明允许的值,但似乎可以为IPv6指定protocol字段。