首页 > 解决方案 > socket() 中“type”为 SOCK_DGRAM 或 SOCK_STREAM 时是否需要指定“protocol”?

问题描述

来自 APUE

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

在哪里:

可以SOCK_DGRAM 使用IPPROTO_UDP,但不能使用IPPROTO_TCP

可以SOCK_STREAM 使用IPPROTO_TCP,但不能使用IPPROTO_UDP

如果答案是肯定的,这是否意味着我们不需要指定protocol何时typeSOCK_DGRAMSOCK_STREAM

标签: clinuxsocketstcpudp

解决方案


从手册页socket(2)

协议指定与套接字一起使用的 特定协议。通常只存在一个协议来支持给定协议族中的特定套接字类型,在这种情况下,协议可以指定为 0。但是,可能存在许多协议,在这种情况下,必须在此指定特定协议方式。要使用的协议号特定于进行通信的“通信域”;见协议(5)。请参阅 getprotoent(3) 了解如何将协议名称字符串映射到协议编号。

因此是否需要指定协议字段取决于类型字段。假设域是AF_INET,即 IPv4,则协议字段应设置为 0SOCK_DGRAMSOCK_STREAM。的手册页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) 函数作为 socket(AF_INET, socket_type, protocol) 调用来创建 IP 套接字。有效的套接字类型是 SOCK_STREAM 用于打开 tcp(7) 套接字,SOCK_DGRAM 用于打开 udp(7) 套接字,或 SOCK_RAW 用于打开 raw(7) 套接字以直接访问 IP 协议。protocol 是要接收或发送的 IP 头中的 IP 协议。 协议的唯一有效值是 TCP 套接字的 0 和 IPPROTO_TCP,以及 UDP 套接字的 0 和 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字段,尽管手册页没有说明允许哪些值。


推荐阅读