《UNIX网络编程(卷一)》第一至六章学习笔记

这篇博客详细介绍了UNIX网络编程卷一中的关键概念,包括TCP和UDP的区别,传输层的功能,TIME_WAIT状态的作用,以及套接字编程的基本原理。内容涵盖TCP的可靠性和流量控制,UDP的无连接特性,套接字地址结构,字节序转换函数,以及基本的TCP套接字编程和I/O复用模型如select和poll。此外,还讨论了如何处理服务器终止、网络字节序和主机字节序的转换,以及数据格式问题。
摘要由CSDN通过智能技术生成
声明
本笔记尽量不涉及SCTP、IPv6以及Unix平台特定的相关知识等.便于学习Winsock的读者阅读.
第一章 简介 
说明:相关内容请阅读本博客关于计算机网络的笔记http://t.cn/zjQjulJ,此处不再赘述.
第二章 传输层:TCP和UDP
用户数据包协议UDP
      用UDP进行网络编程所碰到的问题是 缺乏可靠性,我们也称UDP提供 无连接的(connectionless)服务,因为UDP客户与服务器不必存在长期的关系.
传输控制协议TCP
       TCP提供客户与服务器的连接.一个TCP客户建立与一个给定服务器的连接,并跨该连接与对应服务器交换数据,然后终止连接; TCP提供可靠性.当TCP向另一端发送数据时,它要求对端返回一个确认.如果确认没有收到,TCP自动重传数据并等待更长时间.在数次重传失败后,TCP才放弃.UDP提供不可靠的数据报传送.UDP本身不提供确认、序列号、RTT估算、超时及重传等机制; TCP提供流量控制.TCP总是告诉对端它能够接收多少字节的数据,这称为通告窗口; TCP连接是全双工的,这意味着在给定的连接上应用进程在任何时刻既可以发送也可以接收数据.
TIME_WAIT状态
(1)、实现终止TCP全双工链接的可靠性,即保证tcp连接可靠断开
      解释:必须处理连接终止序列四个分节中任何一个分节丢失的情况(例如,主动关闭一端发送的ACK丢失,则可能再次收到FIN,而重新发送ACK)
(2) 让老的重复分节在网络中消失
      解释:假设在一对IP及端口上有一个连接,关闭这个连接后立即又建立起新的连接,后一个连接为前一个的化身,因为IP和端口相同,TCP必须防止来自某个连接的老分组在连接终止后再现,从而影响新连接的数据交互,所以tcp不能给处于TIME_WAIT状态的连接启动新的化身,从而被误解成属于同一连接.
      至于时间规定为2MSL(最长分节生命期),TCP规定一个分节在网络中最大生存时间是MSL,这足够让某个方向上的分节最多存活MSL秒即被丢弃,另一个方向的应答最多存活MSL秒也被丢弃,通过这个规则,就能保证当成功建立一个TCP连接时,来自该链接的之前所有连接的老的重复分组在网络中已消失.
下图所示处于不同局域网的客户主机和服务器通过广域网连接:
下图所示并发服务器让子进程处理客户:
下图所示第二个客服与同一个服务器连接:
TCP输出 
      每一个TCP套接字有一个发送缓冲区,我们可以使用SO_SNDBUF套接字选项来更改缓冲区的大小.当某个应用进程调用Write函数时,内核从该应用进程的缓冲区复制所有数据到所写套接字的发送缓冲区.如果该套接字的发送缓冲区容不下该进程的所有数据该应用进程将被投入睡眠IF该套接字是阻塞的.内核将不从Write系统调用返回,直到应用进程的缓冲区中的所有数据都复制到套接字发送缓冲区.因此,从写一个TCP套接字的Write调用成功返回仅仅表示我们可以重新使用原来的应用进程缓冲区,并不表明对端的TCP或应用.
下图所示应用进程写TCP套接字时的设计的步骤和缓冲区
UDP输出
      这一次我们以虚线框展示套接字发送缓冲区,因为它实际上并不存在.任何UDP套接字都有发送缓冲区大小,不过它仅仅是可写到该套接字的UDP数据报的大小上限.如果一个应用进程写一个大于套接字缓冲区大小的数据报,内核将返回一个错误.既然UDP是不可靠的,它不必保存应用进程数据的一个副本,因此无需一个真正的发送缓冲区.从写一个UDP套接字的Write调用成功返回表示缩所写的数据报或其所有片段已被加入数据链路层的输出队列.如果该队列没有足够的空间存放该数据报或它的某个片段,内核会返回一个错误给应用进程.下图所示应用进程写UDP套接字时涉及的步骤与缓冲区
端口号
     众所周知的端口:0~1023它们绑定于一些服务,这些服务通常确定了某种协议如HTTP协议端口80 ; 经注册的端口:1024~49151它们松散的绑定一些服务,可动态分配 ; 动态和私用端口:49152~65535一般不为服务绑定这些端口,动态分配所用.
第三章 基本套接字编程见解
套接字地址结构
IPv4套接字地址结构通常也称为"网际套接字地址结构".IPv4的POXIS定义如下.
#include<<netinet/in.h>
typedef uint32_t in_addr_t;
struct in_addr
{
 in_addr_t s_addr;            //即uint32_t s_addr 32位的IPv4网络字节序
};
typedef unsigned short int sa_family_t;
#define __SOCKADDR_COMMON(sa_prefix) sa_family_t sa_prefix##family  //C语言中#的用法
struct sockaddr
{
 __SOCKADDR_COMMON (sa_);     //即unsigned short int sin_family; 地址族
 char sa_data[14];            //特定的协议地址
};
struct sockaddr_in
{
 uint8_t sin_len;             //该结构体的长度
 __SOCKADDR_COMMON (sin_);    //即unsigned short int sin_family;协议族 IPv4为AF_INET
 in_port_t  sin_port;         //端口号
 struct     in_addr sin_addr; //32位IPv4网络字节序地址
 unsigned char sin_zero[sizeof (struct sockaddr) - __SOCKADDR_COMMON_SIZE - sizeof (in_port_t) - sizeof (struct in_addr)]; //填充对齐位
};
//一般情况下上述结构体可以具体化如下:
struct sockaddr_in
{
 uint8_t        sin_len;      //带符号8位整数地址结构长度
 sa_family_t    sin_family;   //协议族,IPv4为AF_INET
 in_port_t      sin_port;     //端口号
 struct in_addr sin_addr;     //32位IPv4网络字节序地址
 char           sin_zero[8];  //填充对齐位
};
下图所示IPv4地址结构示意图+POSIX规范要求的数据类型
通用套接字地址结构
      存在通用套接字地址结构的原因是:当作为一个参数传递进任何套接字函数时,套接字地址结构总是以引用的方式(也就是以指向该结构的指针指针)传递的.然而以这样的指针作为参数之一的任何套接字函数必须处理来自所支持的任何协议族的套接字地址结构.不同的协议有不同的套接字地址结构,函数的参数怎么声明这些套接字地址结构的指针类型是一个问题,于是就定义了一个通用套接字地址结构,所有需要套接字地址结构做参数的函数的这个形参都被声明为指向这个通用套接字地址结构的指针的类型.其他套接字地址结构的指针被强制转换为通用套接字地址结构的指针类型. 从应用程序开发的角度来看,这些通用套接字结构的唯一用途就是对指向特定于协议的套接字地址结构的指针执行类型强制转换 通用套接字地址结构体其定义如下:
#include<sys/socket.h>
struct sockaddr 
{
  uint8_t      sa_len;      //该结构体的长度
  sa_family_t  sa_family;   //地址族
  char         sa_data[14]; //特定的协议地址
};
值-结果参数
      一个套接字函数传递一个套接字地址结构时候,该结构总以引用形式来传递,也就是说传递的指向该结构的一个指针,该结构的长度也作为一个参数来传递,不过其传递方式取决于该
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值