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

时间:2016-05-27 04:46:23

标签: c sockets tcp

我正在阅读并尝试了解C,并且几年前我尝试用Java chatUDP编制TCP,并且就像我把它拉下来一样......我做不到。 我想编写套接字并且我正在阅读大量的文档,但总有一部分不清楚,每个踢文档都有一个缺陷。 例如,有一个关于

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

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

3 个答案:

答案 0 :(得分:3)

来自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结构。如有必要,将打开与数据库的连接。

     

...

     

原始结构的定义如下:

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

所以,如果你通过&#34; ip&#34; getprotobyname()它将返回0,这是你正在使用的数字。但即使您不知道协议的名称,直接使用0也总是安全的。

答案 1 :(得分:1)

可能有不同的协议支持特定套接字类型,因此您也可以在protocol中指定socket(2)

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

  

协议规定了与之一起使用的特定协议   插座。通常只有一个协议支持a   在这种情况下,给定协议族中的特定套接字类型   协议可以指定为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

答案 2 :(得分:1)

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

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

socket (AF_INET, SOCK_RAW, IPPROTO_TCP);

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

另一方面:

socket (AF_INET, SOCK_RAW, IPPROTO_RAW);

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