繁体   English   中英

c socket()函数中类型和协议有什么区别?

[英]What is the difference between type and protocol in c socket() function?

我正在阅读并尝试了解C ,并且几年前我尝试使用UDPTCP UDP Java chat程序,并且尽可能地将其删除...我无法做到。 我想编写套接字并且我正在阅读大量的文档,但总有一部分不清楚,每个踢文档都有一个缺陷。 例如,有一个关于

int socket(int domain, int type, int protocol);

我将使用的域显然是AF_INET ,如果我想要TCP套接字,我认为类型应该是SOCK_STREAM ,但什么是协议? 文档说它应该是0 ...为什么??? 它是什么?

从socket的手册页:

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

根据协议的手册页:

此文件是纯ASCII文件,描述了TCP / IP子系统中可用的各种DARPA Internet协议。 应该参考它而不是使用ARPA包含文件中的数字,或者更糟糕的是,只是猜测它们。 这些数字将出现在任何IP标头的协议字段中。

每行的格式如下:

协议号别名...

...

/ etc / protocols协议定义文件。

在我的linux盒子上的/ etc / protocols文件中:

ip      0       IP              # internet protocol, pseudo protocol number
hopopt  0       HOPOPT          # hop-by-hop options for ipv6
icmp    1       ICMP            # internet control message protocol
igmp    2       IGMP            # internet group management protocol
ggp     3       GGP             # gateway-gateway protocol
ipencap 4       IP-ENCAP        # IP encapsulated in IP (officially ``IP'')
st      5       ST              # ST datagram mode
tcp     6       TCP             # transmission control protocol
cbt     7       CBT             # CBT, Tony Ballardie <A.Ballardie@cs.ucl.ac.uk>
egp     8       EGP             # exterior gateway protocol
igp     9       IGP             # any private interior gateway (Cisco: for IGRP)
bbn-rcc 10      BBN-RCC-MON     # BBN RCC Monitoring
...

并根据getprotocol的手册页:

getprotobyname()函数从数据库返回与协议名称名称匹配的条目的protoent结构。 如有必要,将打开与数据库的连接。

...

protoent结构定义如下:

 struct protoent { char *p_name; /* official protocol name */ char **p_aliases; /* alias list */ int p_proto; /* protocol number */ } 

因此,如果您将“ip”传递给getprotobyname(),它将返回0,这是您正在使用的数字。 但即使您不知道协议的名称,直接使用0也总是安全的。

可能有不同的协议来支持特定的套接字类型,这就是为什么你也可以在socket(2)指定protocol的原因。

从联机帮助页(强调我的):

该协议指定了与套接字一起使用的特定协议。 通常,只有一个协议支持给定协议族中的特定套接字类型,在这种情况下协议可以指定为0. 但是,可能存在许多协议,在这种情况下,必须在此指定特定协议方式。

因此,它不是强制性的指定协议为0 实际上0意味着标准库将为您找出正确的协议。 但是你可以明确地指定它,这样做是完全有效的。

在Linux上,您可以通过以下操作查看可用的协议:

$ cat /etc/protocols
# Internet (IP) protocols
#
# Updated from http://www.iana.org/assignments/protocol-numbers and other
# sources.
# New protocols will be added on request if they have been officially
# assigned by IANA and are not historical.
# If you need a huge list of used numbers please install the nmap package.

ip  0   IP      # internet protocol, pseudo protocol number
hopopt  0   HOPOPT      # IPv6 Hop-by-Hop Option [RFC1883]
icmp    1   ICMP        # internet control message protocol
igmp    2   IGMP        # Internet Group Management
ggp 3   GGP     # gateway-gateway protocol
ipencap 4   IP-ENCAP    # IP encapsulated in IP (officially ``IP'')
st  5   ST      # ST datagram mode

socket()的最后一个协议参数可以与raw包一起使用。 我会尝试解释它。

如果使用原始套接字从TCP堆栈获取数据包,则可以使用此参数控制要发送/接收的数据包数据量。

socket (AF_INET, SOCK_RAW, IPPROTO_TCP);

上面的调用将为您提供一个原始数据包,其中内核将处理数据包到IP头。 您必须在发送数据包时手动填写其余数据包,或者当您读取数据包时,内核将提供TCP标头的内容以及数据。

另一方面:

socket (AF_INET, SOCK_RAW, IPPROTO_RAW);

使用IPPROTO_RAW ,您可以从IP层向上控制数据包。 即内核将为您提供以太网头的服务,其余的数据包在您的控制之下。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM