UNP读书笔记第4章--基本TCP套接字编程

基本TCP客户/服务的套接字函数调用流程图

在这里插入图片描述

socket 函数

  • socket函数:通常protocol参数填0即可,因为family参数和type参数唯一确定protocol。

在这里插入图片描述

family参数:其中AF_xx 和 PF_xx的值是一样的,所以两者可以互相替换(AF:Address, PF:Protocol)

在这里插入图片描述

typ参数:分别对应TCP、UDP、SCTP和本地的套接字协议

在这里插入图片描述

connect函数

  • connect函数:注意connect失败后,不能继续用上一次的sockfd调用connect,而是先close sockfd,再调用socket返回新的sockfd,然后才能调用connect

在这里插入图片描述

connect函数需要注意的点多一些:

如果sockfd是TCP套接字:

  1. 若TCP客户没有收到SYN分节,则返回ETIMEOUT错误。(三次握手的第二次握手失败)
    • 这里还会在一段时间内按规定间隔重复发送SYN分节,如果都没收到才会返回该错误
  2. 硬错误:若TCP服务端对TCP客户的SYN分节的响应是RST分节(表明服务器主机没有在指定的地址,ip+port,等待连接),返回ECONNREFUSED
  3. 软错误:若TCP客户发出的SYN分节在途中某个路由器引发”目的地不可达“(destination unreachable)ICMP错误,则返回EHOSTUNREACH或者ENETUNREACH
    • 客户主机内核保存该消息,然后和第1中情况一样,重复发送SYN分节,都没有响应就返回该错误

这里补充一下,RST分节产生的条件:

  1. 目的地为某个端口的SYN分节到达,但是端口上没有正在监听的服务器
  2. TCP想取消一个已有连接
  3. TCP接收到一个根本不存在的连接的分节

bind函数

在这里插入图片描述

服务端在调用listen之前必须调用bind

而客户端在调用connect之前可以调用bind,也可以不调用bind

myaddr参数:

在这里插入图片描述

bind返回的常见错误:EADDRINUSE(Address already in use).可以通过SO_REUSEPORTSO_REUSEADDR来消除这种错误。

listen参数

在这里插入图片描述

listen函数是TCP服务端专用函数。listen函数有两个需要注意的点:backlog参数的含义和两个队列

当对sockfd调用listen函数时,内核会为sockfd创建两个队列,如下图:

在这里插入图片描述

  • 未完成连接队列

    • 存放正在等待完成三次握手的连接(即处于SYN_RCVD状态的连接)
  • 已完成连接队列

    • 存放已完成三次握手的连接(即处于ESTABLISHED状态的连接)。当对sockfd调用accept函数时,如果已完成队列不空,就立即返回第一个队列给accept函数,否则accept会被阻塞(阻塞套接字情况下),直至有已完成连接进入队列
  • backlog参数的含义:在linux中指的是已完成连接队列的长度(当然,该长度不一定就是backlog的值,有可能加1,或者其x倍)。而在有些系统,backlog是指两个队列长度之和。可以参考这篇博客:(225条消息) 深入探索 Linux listen() 函数 backlog 的含义_杨博东的博客的博客-CSDN博客

当以上两个队列为满时,而刚好有一个客户的SYN分节送到,TCP忽略这个分节,而不是以RST分节作响应。

accept函数

在这里插入图片描述

accept函数需要注意的就是第三个参数是指针,因为传入的cliaddr参数有可能会改变。如果对客户端的地址不感兴趣,可以将accept函数的第2、3参数都传NULL

fork和exec

在这里插入图片描述

这里主要是fork和exec在网络编程的应用,而不是其本身。

父进程在调用fork之前打开的文件描述符,在fork返回后,都和子进程共享。也就是说这些文件描述符的引用计数+1.

exec是指一系列以exec开头的函数,作用都是在一个进程调用另一个程序。

这里同样需要注意exec对于网络编程的影响:进程在调用exec之前打开着的文件描述符通常跨exec继续保持打开。若要改变这一特性,fctnl设置FD_CLOEXEC,意思是当exec之后,关闭这个文件描述符。

close和shutdown

在这里插入图片描述

这里的close函数只是考虑关闭的是套接字的情况。

close一个TCP套接字的默认行为就是将其标志为已关闭,然后立即返回到调用进程。如果该连接中还有一些数据(已经从应用缓冲区调用write,拷贝的内核缓冲区),TCP会尝试发送完这些数据,最后发送的是正常的TCP连接终止序列(FIN分节

该套接字不能再read和write。

注意:close不是立即关闭连接,而是将sockfd的引用计数减一,为0才真正关闭连接

shutdown是真正的关闭TCP连接(发送FIN分节)

#include<sys/socket.h>
int shutdown(int sockfd,int howto);  //返回成功为0,出错为-1.

该函数的行为依赖于howto的值:

  1. SHUT_RD:值为0,关闭连接的读这一半。
  2. SHUT_WR:值为1,关闭连接的写这一半。
  3. SHUT_RDWR:值为2,连接的读和写都关闭。

getsockname和getpeername

在这里插入图片描述

函数作用顾名思义,不做解释。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值