abor的实现源码

本文探讨了带外数据的概念,特别是在TCP协议中的实现,以及FTP协议中ABOR命令的作用。ABOR命令用于中断数据传输,通过紧急模式在传输层中实现。在服务器端,根据状态不同,ABOR命令可能导致不同的响应。实现ABOR命令涉及开启套接字的带外数据接收、信号处理等步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

带外数据

什么是带外数据?带外数据是什么意思?

许多传输层都支持带外数据,有时候也称为快速数据。之所以有带外数据的概念,是因为有时候在一个网络连接的终端想“快速”的告诉网络另一边的终端一些信息。这个“快速”的意思是我们的“提示”信息会在正常的网络数据(有时候称为带内数据In-Band data)之前到达网络另一边的终端.这说明,带外数据拥有比一般数据高的优先级。但是不要以为带外数据是通过两条套接字连接来实现的.事实上,带外数据也是通过以有的连接来传输。

TCP的带外数据

头部标志: URG位,紧急指针。

数据包中:一个紧急指针只指向一个字节的带外数据的后已字节位置。紧急数据时插在正常数据流中进行传输。紧急指针用于指出带外数据字节在正常字节流中的位置。

为何不直接将一个字节的紧急数据放在紧急指针哪里呢?

因为TCP数据包在ip层可能被拆包,成为多个数据段。一个包含紧急数据的数据包被拆成两个数据包,那么这两个包有的tcp头部有相同的紧急指针(和UGR)。如果将紧急数据直接放在紧急指针的内存处,那么将多出一个紧急数据!所以,不该将紧急数据放在TCP头部。

abor命令的作用

ftp中的abor命令是用于中断当前正在传输的数据连接通道,它并不会将控制连接通道断开,也就是说客户端与ftp服务端的会话仍然是存在的。

如果当前客户端和ftp服务端正在进行数据传输,那么客户端向服务器发送的abor命令是通过紧急模式来传输的,否则是按正常模式传输的。所以要处理ABOR命令,需要开启紧急模式接收数据。

服务器接收这个命令时可能处在两种状态:(1)FTP服务命令刚好完成(上传或下载结束),或者(2)FTP服务器命令还在执行中(上传或下载还在继续)。

第一种情况:服务器关闭数据连接(如果数据连接是打开的)回应226代码,表示放弃命令已经成功处理。

第二种情况:服务器放弃正在进行的FTP服务,关闭数据连接,返回426响应代码,表示请求服务异常终止。然后服务器发送226响应代码,表示放弃命令成功处理。

abor命令的实现

1.将套接字开启接收带外数据的功能

//紧急数据的接收
// 开启套接字fd接收带外数据的功能
void activate_oobinline(int fd)
{
	//表示开启
	int oob_inline = 1;
	int ret;
	ret = setsockopt(fd, SOL_SOCKET, SO_OOBINLINE, &oob_inline, sizeof(oob_inline));
	if (ret == -1) {
		ERR_EXIT("setsockopt");
	}
}

2.设置进程能够接收文件描述符产生的SIGURG信号

F_SETOWN   设置将接收SIGIO和SIGURG信号的进程id或进程组id,进程组id通过提供负值的arg来说明(arg绝对值的一个进程组ID),否则arg将被认为是进程id。

// 当套接字fd上有带外数据的时候,将产生SIGURG信号
// 该函数设定当前进程能够接收fd文件描述符所产生的SIGURG信号
void activate_sigurg(int fd)
{
	int ret;
	//设置异步I/O所有权
	/*
	F_SETOWN命令允许我们指定用于接收SIGIO和SIGURG信号的套接字属主(进程ID或进程组ID)。
	其中SIGIO信号是套接字被设置为信号驱动式I/O型后产生的,SIGURG信号是在新的带外数据
	到达套接字时产生的。
	*/
	ret = fcntl(fd, F_SETOWN, getpid());
	if (ret == -1) {
		ERR_EXIT("fcntl");
	}
}

3.注册信号

//接收到SIGURG信号,处理函数是handle_sigurg
signal(SIGURG, handle_sigurg);

4.设置信号处理函数

最主要的就是要关闭数据连接套接字,而且设置相应状态,表示是接收到了abor

//一旦产生一个SRGURG信号,意味着发送了一个带外数据(紧急数据)
//也就是abor命令可能发送过来了
void handle_sigurg(int sig)
{
	//判断当前是否处于数据传输的状态
	//如果不是处于数据传输的状态,则不用处理
	if (p_sess->data_fd == -1) {
		return;
	}

	//如果是带外数据传送的,就不会执行do_abor函数了
	char cmdline[MAX_COMMAND_LINE] = {0};
	//接收一行数据,也就是abor命令
	int ret = readline(p_sess->ctrl_fd, cmdline, MAX_COMMAND_LINE);
	if (ret <= 0) {
		ERR_EXIT("readline");
	}

	//去除\r\n
	str_trim_crlf(cmdline);
	//判断收到的是否是abor命令(abor命令没有参数,直接比较就行)
	if (strcmp(cmdline, "ABOR") == 0 
		|| strcmp(cmdline, "\377\364\377\362ABOR") == 0) {
		//收到了abor命令
		p_sess->abor_received = 1;
		//即使处于数据连接,也要断开数据连接通道
		shutdown(p_sess->data_fd, SHUT_RDWR);
	} else {
		ftp_reply(p_sess, FTP_BADCMD, "Unknown command.");
	}
}

5.给客户端应答

比如当前正处于数据传输中,由于在信号处理函数中关闭了数据连接套接字,那么read就会返回-1。然后进行相应提示。

还有一种情况是:abor命令接收的时候,可能正处于上传、下载的状态,在这个过程中因为限速的原因,有可能会使进程睡眠,当睡醒之后,就要判断是否是接收到了abor命令,如果是break循环,然后进行相应提示。

while (1) {
		//从数据套接字接收数据
		ret = read(sess->data_fd, buf, sizeof(buf));
		if (ret == -1) {
			if (errno == EINTR) {
				continue;
			} else {
				flag = 2;
				break;
			}
		}
		else if (ret == 0) {
			flag = 0;
			break;
		}

		//读取了一定数据之后需要判断是否限速
		limit_rate(sess, ret, 1);
		//睡醒之后判断是否收到了abor,如果是直接break,其实没有也可以,返回去
		//的时候read会返回-1,因为已经关闭了数据连接套接字了
		if (sess->abor_received) {
			flag = 2;
			break;
		}

		//写入文件中
		if (writen(fd, buf, ret) != ret) {
			flag = 1;
			break;
		}
	}

 

### 关于FTP ABOR命令的用途和示例 FTP 协议中的 `ABOR` 命令用于终止正在进行的文件传输操作。当客户端发送此命令时,远程服务器会停止当前的数据传输并释放相关资源。如果数据正在从本地主机传送到远程主机,则立即中断;如果是从远程主机接收数据到本地主机,则通过向服务器发送 `ABOR` 指令来请求终止,并丢弃所有接收到的包直到服务器完全停止发送[^1]。 然而需要注意的是,某些旧版本或者特定配置下的 FTP 服务器可能不支持该指令。在这种情况下,只有等到整个文件被传送完毕才会返回控制权给用户界面(ftp>)。另外,在异常情形下(比如网络延迟过高或者其他不可预见的情况),也许不得不手动结束本机上的 ftp 进程以解决问题[^1]。 下面提供了一个简单的 Python 脚本来演示如何利用 ftplib 库实现基本功能以及尝试调用 abort 方法: ```python import ftplib def connect_ftp(host, username='anonymous', password=''): try: session = ftplib.FTP(host) session.login(username, password) # Example commands here... # Attempting to send an 'ABOR' command. result = session.abort() print(f"Abort Command Result: {result}") session.quit() except Exception as e: print(e) if __name__ == "__main__": HOSTNAME_OR_IP = "your_host" USER_NAME = "" PASSWORD = "" connect_ftp(HOSTNAME_OR_IP,USER_NAME,PASSWORD ) ``` 以上脚本展示了连接至指定地址的 FTP 服务端之后执行一些基础动作再试着发出中止信号的过程。请注意替换掉 `"your_host"` 和其他占位符为你实际使用的值之前不要运行这段代码! 对于 vsftpd 的情况而言,它能够独立运作也可以由像 xinetd 那样的超级守护进程启动多个实例分别处理不同的虚拟主机需求[^2][^3]。这意味着管理员可以灵活调整其工作模式从而满足复杂环境下的定制化要求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值