套接字说明及函数说明

 

        socket通常也称作“套接字”,应用程序通常通过“套接字”向网络发出请求或者响应网络请求。socket位于传输层之上,应用层之下。socket函数基本为系统调用,它是操作系统向网络通信应用程序提供的函数接口。

        Linux套接字编程完全兼容Unix套接字编程,两个平台编程方法是一致的。读者可以重点掌握TCP套接字编程和UDP服务器编程。

1.1.1 套接字说明

Linux&Unix的I/O内涵是系统中一切都是文件。当程序在执行任何形式I/O的时候,程序是在读或者写一个文件描述符从而实现操作文件。但是,这个文件可能是一个socket网络连接、目录、FIFO、管道、终端、外设、磁盘上的文件。socket是使用标准Linux文件描述符和其他进程进行通信的。

利用socket编程, 会涉及流(stream)、连接(connection)、阻塞(block)、非阻塞(non-block)、同步(synchronous)、异步(asynchronous)、长连接、短连接、IP地址、端口、字节顺序等概念,这些概念将在后文加以介绍。

1.   套接字说明

(1)套接字网络层次说明

图18-1画出了套接字位于网络中的层次,它位于传输层之上,应用层之下。socket编程是通过一系列系统调用完成应用层协议。如ftp、telnet、http等应用层协议都是通过socket编程来实现。

       

                                                      图18-1 套接字层次图

套接字是对网络中应用进程之间进行双向通信的抽象,提供了应用层进程利用网络协议栈交换数据的机制。

从套接字所处的地位来讲,套接字上联应用进程,下联网络协议栈,是应用程序通过网络协议栈进行通信的接口,是应用程序与网络协议栈进行交互的接口。

从实现的角度来讲,套接字系统函数是一个复杂的软件模块,包含了一定的数据结构和许多选项,由操作系统内核管理。

从使用的角度来讲,利用套接字函数编程非常简单。

总之,套接字是网络通信的基石。套接字函数是一种网络通信API,程序员可以用之开发网络程序。

 

(2)IP地址与端口

端口是指网络中面向连接服务和无连接服务的通信协议端口,它是一种抽象的软件结构,包括一些数据结构和I/O(基本输入输出)缓冲区。

IP地址用来标识网络中不同主机的地址,而端口号就是标识同一台主机上不同网络通信进程的地址,IP地址和端口号合起来标识网络中唯一的进程。

如果把IP地址比作一间房子 ,端口就是出入这间房子的门。真正的房子只有几个门,但是一个IP地址的端口可以有65536(即2^16)个之多。端口是通过端口号来标记的,端口号只能是整数,范围是从0 到65535(2^16-1)。其中端口1~1024是系统保留端口。

其中一次socket通信连接,会涉及源IP地址、源端口、目的IP地址、目的端口四个要素。源IP地址、源端口标识客户端进程,其中源端口为操作系统随机分配的;目的IP地址、目的端口标识服务端进程,其中目的端口是由应用程序指定的。

 

(3)socket编程说明

Linux系统是通过提供套接字(socket)函数来进行网络编程的。socket技术提供了在TCP/IP模型各个层上的编程支持,该技术是在内核处理收到的各层协议数据,然后应用程序以文件操作方式接收内核传来的数据。应用程序对文件处理是通过一个文件描述符来进行的,socket文件描述符可以看成普通的文件描述符来进行操作,这就是Linux设备无关性的好处,可以通过对文件描述符读写操作来实现网络间数据流的传输。

2.TCP连接与关闭

(1)TCP建立连接

    TCP连接时,服务器和客户端需要通过三路握手才正式建立连接。下图18-2画出了客户端与服务端三路握手的实现。

图18-2 TCP三路握手图

TCP连接的过程说明如下:

①    服务器绑定端口进行通信侦听,通过调用socket、bind、listen函数完成。

②      客户端通过调用connect进行发起对服务端的连接,客户端发送一个SYN分节x告诉服务器客户端使用的端口以及TCP连接的初始序号。

③      服务器在收到客户端的SYN报文后,将返回一个SYN+ACK的报文,ACK分节x+1(请求序号加1)表示客户端的请求被接受,SYN分节y为服务器请求客户端进行确认。

④      客户端发送ACK分节y+1对服务端SYN分节y进行确认,此时三路握手完成。

 

(2)TCP连接关闭

    TCP连接关闭时双方需要通过四次会话,其流程如下图18-3所示。

图18-3 TCP连接关闭图

TCP一般需要用四个分节终止一个连接,终止具体流程描述如下:

①  TCP客户端发送一个FIN分节M,用来关闭客户到服务器的数据传送。

②  服务器收到这个FIN,它发回一个ACK,确认序号为收到的M序号加1。

③  服务器开始关闭客户端的连接,发送一个FIN分节N给客户端。

④  客户段发回ACK报文确认,并将确认序号设置为收到序号N加1。

 

(3)TCP连接中的分组交换

图18-4是TCP连接中的分组交换图,它画出了客户端和服务器连接的全过程,并标明通信过程中的连接状态。其中TIME_WAIT状态是执行主动关闭的那一端(本图的客户端)进入这种状态,在该状态的持续时间是2MSL(最长分节生命周期),这个状态的存在是为了保证ACK分节发送的成功。

图18-4 TCP连接中的分组交换

 

摘录自《深入浅出Linux工具与编程》
<think> 根据用户的问题,用户希望了解socket套接字中ioctl函数的参数说明。 从引用中,我们可以提取关于ioctl函数socket编程中的相关信息: 引用[1]提到了ioctlsocket函数(Windows平台)用于设置非阻塞套接字,但用户的问题是关于ioctl函数(Unix/Linux系统)的。 引用[4]详细介绍了ioctl函数的用法,包括函数原型和参数说明,这是我们要重点参考的。 注意:在Unix/Linux系统中,ioctl是一个系统调用,用于设备控制,包括套接字。在Windows中,类似功能的函数是ioctlsocket。 由于用户明确提到“socket套接字中ioctl函数”,且引用[4]是关于Unix/Linux的ioctl,因此我们按照引用[4]的内容进行回答。 引用[4]中ioctl函数的原型: #include <sys/ioctl.h> int ioctl(int fd, unsigned long cmd, ... /* void *arg */); 参数说明: - fd:文件描述符,指向已打开的设备文件(对于套接字,就是套接字描述符)。 - cmd:无符号长整型,预定义或自定义的命令码(例如,对于套接字,常用的命令码有SIOCATMARK, FIOASYNC等)。 - arg:可变参数,通常是一个指针,指向的数据类型由cmd决定,用于传递输入或输出数据。 但是,用户特别询问的是在socket套接字中的参数说明,因此我们需要具体说明套接字编程中常用的cmd以及对应的arg类型。 补充说明:在套接字编程中,ioctl函数可以用于多种控制操作,例如: - 设置或获取套接字的异步I/O标志(FIOASYNC) - 检查带外数据标记(SIOCATMARK) - 获取待处理数据的长度(FIONREAD) 下面详细说明这几个常用操作: 1. 获取套接字接收缓冲区中待读取的数据量(FIONREAD): cmd: FIONREAD arg: 指向int类型的指针,ioctl调用成功后,该int值会被设置为接收缓冲区中可读的字节数。 2. 设置或清除异步I/O标志(FIOASYNC): cmd: FIOASYNC arg: 指向int类型的指针,如果该int值为非0,则启用套接字的异步I/O(即当I/O操作可用时发送SIGIO信号);如果为0,则禁用。 3. 检查带外数据标记(SIOCATMARK): cmd: SIOCATMARK arg: 指向int类型的指针,用于返回结果。如果套接字当前处于带外数据标记位置(即下一个要读取的数据是带外数据),则arg指向的int被设置为非0值;否则为0。 需要注意的是,ioctl函数在成功时返回0,失败时返回-1并设置errno。 另外,引用[3]提到SOCK_DGRAM类型的套接字,但并未直接与ioctl参数相关,故不在此展开。 由于用户只要求参数说明,因此我们重点解释参数,并给出一个简单的使用示例(可选,但用户没有要求示例,因此可以省略或简要提及)。 因此,回答如下: </think> 在 socket 编程中,`ioctl()` 函数用于对套接字进行底层控制操作。该函数的参数说明如下(基于 Unix/Linux 系统): ### 函数原型 ```c #include <sys/ioctl.h> int ioctl(int sockfd, unsigned long cmd, void *arg); ``` ### 参数详解 1. **`sockfd`** - **类型**: 整型文件描述符 (`int`) - **作用**: 已打开的套接字描述符(如通过 `socket()` 创建的套接字)。 - **示例**: ```c int sockfd = socket(AF_INET, SOCK_STREAM, 0); // 创建套接字 ``` 2. **`cmd`** - **类型**: 无符号长整型 (`unsigned long`) - **作用**: 预定义的命令码,指定要执行的控制操作。常用套接字命令包括: - `FIONBIO`: 设置/清除非阻塞模式 ```c int opt = 1; // 1:非阻塞, 0:阻塞 ioctl(sockfd, FIONBIO, &opt); ``` - `FIONREAD`: 获取接收缓冲区中的待读字节数 ```c int bytes_avail; ioctl(sockfd, FIONREAD, &bytes_avail); ``` - `SIOCATMARK`: 检查是否位于带外数据标记处 ```c int is_at_mark; ioctl(sockfd, SIOCATMARK, &is_at_mark); ``` 3. **`arg`** - **类型**: 泛型指针 (`void*`) - **作用**: 指向与 `cmd` 关联的数据结构的指针,用于输入或输出。具体类型由 `cmd` 决定: - `FIONBIO`/`FIONREAD`: 指向 `int` 的指针 - `SIOCATMARK`: 指向 `int` 的指针(结果:1 表示在标记处,0 表示不在) - 其他命令(如网络接口配置)可能指向 `struct ifreq` 等结构体 [^3][^4]。 ### 返回值 - **成功**: 返回 `0` - **失败**: 返回 `-1` 并设置 `errno`(如 `EBADF` 无效描述符、`EINVAL` 无效命令) ### 注意事项 1. **阻塞 vs. 非阻塞** `FIONBIO` 用于切换套接字阻塞模式,直接影响 `recv()`/`send()` 等函数的阻塞行为 [^1]。 2. **平台差异** Windows 使用 `ioctlsocket()` 替代,参数类似但命令码不同(如 `FIONBIO` 相同)[^1]。 3. **替代函数** 部分操作可通过 `fcntl()`(如非阻塞模式)或 `setsockopt()`(更高级选项)实现 [^2][^4]。 ### 示例代码 ```c // 获取待读数据量 int bytes_ready; if (ioctl(sockfd, FIONREAD, &bytes_ready) == 0) { printf("可读字节数: %d\n", bytes_ready); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值