《TCP/IP 网络编程》第二章——套接字类型与协议设置(学习笔记)

代码链接

第二章 套接字类型与协议设置

本章需了解创建套接字时调用的 socket 函数。

2.1 套接字协议及数据传输特性

2.1.1 关于协议

协议是为了完成数据交换而定好的约定

2.1.2 创建套接字

#include <sys/socket.h>
int socket(int domain, int type, int protocol);
/*
成功时返回文件描述符,失败时返回-1
domain:套接字中使用的协议族(Protocol Family)信息
type:套接字数据传输类型信息
protocol:计算机间通信中使用的协议信息
*/

下面给出详细说明

2.1.3 协议族(protocol Family)

通过 socket 函数的第一个参数传递套接字中使用的协议分类信息。此协议分类信息称为协议族,可分如下几类。

下表为头文件 sys/socket.h 中声明的协议族

名称协议族
PF_INETIPV4 互联网协议族
PF_INET6IPV6 互联网协议族
PF_LOCAL本地通信 Unix 协议族
PF_PACKET底层套接字的协议族
PF_IPXIPX Novel 协议族

本书着重讲解 PF_INET 对应的 IPV4 互联网协议族。另外,套接字中实际采用的最终协议信息是通过 socket 函数的第三个参数传递的。在指定的协议族范围内通过第一个参数决定第三个参数。

2.1.4 套接字类型(Type)

套接字类型指的是套接字的数据传输方式,通过 socket 函数的第二个参数进行传递,只有这样才能决定创建的套接字的数据传输方式。

Q:已经通过第一个参数传递了协议族信息,为什么还要决定数据传输方式?

A:决定了协议族并不能同时决定数据传输方式。换言之,socket 函数第一个参数 PF_INET 协议族中也存在多种数据传输方式。

2.1.5 套接字类型 1:面向连接的套接字(SOCK_STREAM)

如果向 socket 函数的第二个参数传递 SOCK_STREAM,将创建面向连接的套接字。

传输方式特征整理如下:

  • 传输过程中数据不会消失
  • 按序传输数据
  • 传输的数据不存在数据边界(Boundary)

下面假设一种情形

传输数据的计算机通过 3 次调用 write 函数传递了 100 字节的数据,但接收数据的计算机仅仅通过调用 1 次 read 函数调用就接受了全部 100 个字节。

收发数据的套接字内部有缓冲(buffer),简言之就是字节数组。通过套接字传输的数据将保存到该数组。因此,收到数据并不意味着马上调用 read 函数。只要不超过数组容量,则有可能在数据填满缓冲后通过 1 次 read 函数调用读取全部,也有可能分成多次 read 函数调用进行读取。

所以说面向连接的套接字不存在数据边界。

Q:套接字缓冲已满是否意味着数据丢失

A:不会,会根据接收端状态传输数据,如果数据出错会提供重传服务。

套接字连接必须一一对应。面向连接的套接字是可靠的、按序传递的、基于字节的面向连接的数据传输方式套接字。

2.1.6 套接字类型 2:面向消息的套接字(SOCK_DGRAM)

如果向 socket 函数的第二个参数传递 SOCK_DGRAM,则将创建面向消息的套接字。

传输方式特征整理如下:

  • 快速传输而非传输顺序
  • 传输的数据可能丢失也可能损毁
  • 传输的数据有数据边界
  • 限制每次传输的数据大小

面向消息的套接字是不可靠的、不按序传递的、以数据的高速传输为目的的套接字。

面向消息的套接字不存在连接的概念。

2.1.7 协议的最终选择

socket 函数的第三个参数决定最终采用的协议。

Q:前面两个参数还不足以决定采用协议吗?为什么还要传递第三个参数?

A:传递前两个参数即可创建所需套接字,大部分情况下可以向第三个参数传递 0,除非遇到以下情况:

『同一协议族中存在多个数据传输方式相同的协议』

本书是基于 IPv4 展开的,且是面向连接的数据传输。满足这两个条件的协议只有 IPPROTO_TCP,因此可以调用如下 socket 函数创建套接字,这种套接字称为 TCP 套接字。

int tcp_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);

满足 IPv4 协议族,且选择面向消息的数据传输方式 SOCK_DGRAM,满足这两个条件的协议只有 IPPROTO_UDP,因此可以调用如下 socket 函数创建套接字,这种套接字称为 UDP 套接字。

int udp_socket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);

2.1.8 面向连接的套接字:TCP 套接字示例

用第一章 hello_server.c 和 hello_client.c 修改部分,以验证TCP套接字性质『传输的数据不存在数据边界』

修改好的代码见:tcp_server.c 文件和 tcp_client.c 文件。

修改好的代码与书上略有不同,结果一致。因为本人认为 read 函数调用次数虽然数值最后和字符串长度一致,因为每次只读取一个字节,但是含义并不相同。所以用 call_cnt 变量代替。

编译运行:

gcc tcp_client.c -o hclient.exe
gcc tcp_server.c -o hserver.exe
./hserver.exe 9190
./hclient.exe 127.0.0.1 9190

运行结果

wzy@wzypc:~/TCP-IP-NetworkNote/chapter-02$ ./hclient.exe 127.0.0.1 9190
Message from server : Hello World! 
Function read call count: 13

从运行结果可以看出,服务器端发送了 13 字节的数据,客户端调用 13 次 read 函数进行读取。

2.2 Windows 平台下的实现及验证

2.3 习题

  1. 什么是协议?在收发数据中定义协议有何意义?

协议是为了完成数据交换而定好的约定。意义是能够让计算机之间正常进行数据交换。

  1. 面向连接的套接字 TCP 套接字传输特性有 3 点,请分别说明。

可靠、按序传输、传输的数据不存在数据边界

  1. 下面那些是面向消息的套接字的特性?

a. 传输数据可能丢失

c. 以快速传递为目标

e. 与面向连接的套接字不同,不存在连接概念

错误选项

b. 没有数据边界(Boundary)

d. 不限制每次传递数据的大小

  1. 下列数据适合用哪类套接字进行传输?

演唱会现场直播的多媒体数据(UDP)

某人压缩过的文本文件(TCP)

网上银行用户与银行之间的数据传递(TCP)

  1. 何种类型的套接字不存在数据边界?这类套接字接收数据时应该注意什么?

TCP。写入速度不要太快,还需正确拿走所需数据。

  1. 代码修改题

略,大致思路和 2.1.8 代码差不多,多个 sleep 函数大概就能实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值