11-附录:SOCKET设置备查

1. socket初始化

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

  • domain -- 指定使用何种的地址类型

PF_INET, AF_INET: Ipv4网络协议

PF_INET6, AF_INET6: Ipv6网络协议

AF = Address Family

PF = Protocol Family

  • type -- 设置通信的协议类型

SOCK_STREAM: 提供面向连接的稳定数据传输,即TCP协议。

OOB: 在所有数据传送前必须使用connect()来建立连接状态。

SOCK_DGRAM: 使用不连续不可靠的数据包连接。

SOCK_SEQPACKET: 提供连续可靠的数据包连接。

SOCK_RAW: 提供原始网络协议存取。

SOCK_RDM: 提供可靠的数据包连接。

SOCK_PACKET: 与网络驱动程序直接通信。

  • protocol -- 指定socket所使用的传输协议编号

这一参数通常不具体设置,一般设置为0即可

2. setsockopt

使用格式:

socket.setsockopt(level, optname, value)

在套接字级别上(SOL_SOCKET),option_name可以有以下取值:

SO_DEBUG,打开或关闭调试信息。

SO_REUSEADDR,打开或关闭地址复用功能。

SO_DONTROUTE,打开或关闭路由查找功能。

SO_BROADCAST,允许或禁止发送广播数据。

SO_SNDBUF,设置发送缓冲区的大小。其上限为256 * (sizeof(struct sk_buff) + 256),下限为2048字节。

SO_RCVBUF,设置接收缓冲区的大小。上下限分别是:256 * (sizeof(struct sk_buff) + 256)和256字节。

SO_KEEPALIVE,套接字保活。

SO_OOBINLINE,紧急数据放入普通数据流。

SO_NO_CHECK,打开或关闭校验和。

SO_PRIORITY,设置在套接字发送的所有包的协议定义优先权。

SO_LINGER,如果选择此选项, close或 shutdown将等到所有套接字里排队的消息成功发送或到达延迟时间后才会返回. 否则, 调用将立即返回。

SO_PASSCRED,允许或禁止SCM_CREDENTIALS 控制消息的接收。

SO_TIMESTAMP,打开或关闭数据报中的时间戳接收。

SO_RCVLOWAT,设置接收数据前的缓冲区内的最小字节数。

SO_RCVTIMEO,设置接收超时时间。

SO_SNDTIMEO,设置发送超时时间。

SO_BINDTODEVICE,将套接字绑定到一个特定的设备上。

SO_ATTACH_FILTER和SO_DETACH_FILTER。

3. TCP可靠,UDP不可靠的原因

SO_RCVBUF 、SO_SNDBUF

每个TCP socket在内核中都有一个发送缓冲区和一个接收缓冲区,TCP的全双工的工作模式以及TCP的滑动窗口便是依赖于这两个独立的buffer以及此

buffer的填充状态。接收缓冲区把数据缓存入内核,应用进程一直没有调用read进行读取的话,此数据会一直缓存在相应socket的接收缓冲区内。

再啰嗦一点,不管进程是否读取socket,对端发来的数据都会经由内核接收并且缓存到socket的内核接收缓冲区之中。read所做的工作,就是把内核缓冲区中的数据拷贝到应用层用户的buffer里面,仅此而已。

进程调用send发送的数据的时候,将数据拷贝进入socket的内核发送缓冲区之中,然后send便会在上层返回。换句话说,send返回之时,数据不一定

会发送到对端去,send仅仅是把应用层buffer的数据拷贝进socket的内核发送buffer中。

每个UDP socket都有一个接收缓冲区,没有发送缓冲区,从概念上来说就是只要有数据就发,不管对方是否可以正确接收

对于TCP,如果应用进程一直没有读取,buffer满了之后,发生的动作是:通知对端TCP协议中的窗口关闭。这个便是滑动窗口的实现。保证TCP套接口

接收缓冲区不会溢出,从而保证了TCP是可靠传输。因为对方不允许发出超过所通告窗口大小的数据。 这就是TCP的流量控制,如果对方无视窗口大小

而发出了超过窗口大小的数据,则接收方TCP将丢弃它。 对于UDP,当套接口接收缓冲区满时,新来的数据报无法进入接收缓冲区,此数据报就被丢弃。

TCP相关注意点

  1. tcp服务器一般情况下都需要绑定端口和IP,否则客户端找不到这个服务器
  2. tcp客户端一般不绑定,因为是主动链接服务器,所以只要确定好服务器的ip、port等信息就好,本地客户端可以随机
  3. tcp服务器中通过listen可以将socket创建出来的主动套接字变为被动的,这是做tcp服务器时必须要做的
  4. 当客户端需要链接服务器时,就需要使用connect进行链接,udp是不需要链接的而是直接发送,但是tcp必须先链接,只有链接成功才能通信
  5. 当一个tcp客户端连接服务器时,服务器端会有1个新的套接字,这个套接字用来标记这个客户端,单独为这个客户端服务
  6. listen后的套接字是被动套接字,用来接收新的客户端的链接请求的,而accept返回的新套接字是标记这个新客户端的
  7. 关闭listen后的套接字意味着被动套接字关闭了,会导致新的客户端不能够链接服务器,但是之前已经链接成功的客户端正常通信。
  8. 关闭accept返回的套接字意味着这个客户端已经服务完毕
  9. 当客户端的套接字调用close后,服务器端会recv解堵塞,并且返回的长度为0,因此服务器可以通过返回数据的长度来区别客户端是否已经下线