TCP/IP 学习笔记(2)- 套接字类型与协议设置

原创

上一篇文章我们简单讲了TCP服务端和客户端程序的编写,但是对于里面函数并没有具体的说明。接下来具体说明一下 socket 函数。

socket 函数主要用于创建套接字,它的基本形式如下:

  • int socket (int domain, int type, int protocel)
  • domain: 套接字中使用的协议族信息
  • type: 套接字传输类型信息
  • protocol: 计算机间通信中使用的协议信息
  • 返回值: 成功时返回文件描述符,失败时返回-1

1. 协议族

socket 函数的第一个参数为套接字中使用的协议分类信息,成为协议族,可分为如下几类:

  • PF_INET : IPv4互联网协议族
  • PF_INET6: IPv6互联网协议族
  • PF_LOCAL : 本地通信的UNIX协议族
  • PF_PACKET : 底层套接字的协议族
  • PF_IPX : IPX Novell协议族

之前的例子中,使用的是 PF_INET 协议族,另外套接字中实际采用的最终协议信息是通过 socket 函数的第三个参数传递的。在指定的协议族范围内通过第一个参数决定第三个参数。


2. 套接字类型

套接字类型指的是套接字数据的传输方式,即使用TCP还是UDP传输。

(1)面向连接的套接字(SOCK_STREAM)

如果向 socket 函数的第二个函数传递 SOCK_STREAM , 将创建面向连接套接字。面向连接套接字具有如下特点

  • 传输过程中数据不会丢失。
  • 按顺序传输数据。
  • 传输的数据不存在数据边界。
  • 套接字必须一一对应。

收发数据的套接字中具有缓冲区,通过套接字传输的数据保存在缓冲区中,因此收到数据并不意味之马上调用 recv 函数,只要不超过缓冲区的数据容量,则有可能在数据填充满缓冲后调用一次 read函数读取全部数据。也可能分多次read函数进行读取。因此调用 readwrite 函数的次数没有太大的意义。所以说 传输的数据是不存在数据边界的。

如果缓冲区的数据满了会怎么样呢? 首先调用 read 函数读取缓冲区的部分数据,如果 read 函数的读取速度比接受的速度满,则缓冲取可能被填满。此时套接字无法再接受数据,但即使这样也不会发生数据丢失,因此传输数据的套接字将停止传输。也就是说,面向连接的套接字会根据接收端的状态传输数据,如果传输出错还会重传。

用一句话总结面向连接的套接字就是:
可靠的、按序传输的、基于字节的面向连接的数据传输方式的套接字

(2)面向消息的套接字(SOCK_DGRAM)

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

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

面向消息的套接字比面向连接的套接字具有更快的传输速度,但是无法避免的数据丢失和销毁。另外,每次传输数据大小具有一定的限制,并存在数据边界。存在数据边界意味着接收数据的次数和传输次数相同,总结面向消息的套接字一句话就是:
不可靠的、不按序传递的、以数据的高速传输为目的的套接字。


3. 协议的最终选择

下面介绍 socket 函数的最后一个参数,该参数决定最终采用的协议。前面的程序中,最后一个参数填的0,除非遇到如下情况: 同一协议族中存在多个数据传输方式相同的协议

在参数 PF_INETIPv4 网络族中, SOCK_STREAM 面向连接的数据传输。满足以上两个条件的只有 IPPROTO_TCP, 因此可以使用下面的方式创建 TCP套接字
int tcpsocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);

SOCK_DGRAM 指向的面向消息的传输方式中,满足以上条件的只有 IPPROTO_UDP, 因此可以使用下面的方式创建 UDP套接字
int udpsocket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);


4. Windows中的socket函数

上面介绍的为 Linuxsocket函数,windows中 socket函数跟Linux中的使用是相同,唯一不同的是返回值,这里再次给出 socket 函数的声明:

  • #include <winsock2.h>
  • SOCKET socket(int domain, int type, int protocel)
  • 返回值:成功返回socket句柄,失败返回 INVALID_SOCKET
不会飞的纸飞机
扫一扫二维码,了解我的更多动态。

下一篇文章:创建一个Win32窗口