【Linux学习笔记60】网络的带外数据(紧急数据)

引言

  • 只有TCP才有带外数据,UDP是没有的。
  • 网上也有一种说法,TCP没有真正意义上的“带外数据”。这种说法的由来是在TCP协议中,服务端与客户端之间都通过管道传输数据,比如传输的数据是1字节,没有超过socket中设置的缓冲池的限制的话,这个数据是要等到数据达到缓冲区上限才可以到达对端的。而“带外数据”也并没有什么捷径,也是一样通过这种方法到达对端,只不过会将其标志为紧急数据,提前让对端释放缓冲池内容。
    在这里插入图片描述
  • 需要注意的是,每条紧急数据只能是1字节

如何发送/接收带外数据

发送函数:

#include "head4sock.h"
#include <stdlib.h>
#include <string.h>
#include <strings.h>

#define MAXLINE 80

void usage(const char *info)
{
	printf("Usage: %s <srv's IP> <srv's PORT>\n", info);
	exit(0);
}

int main(int argc, char **argv)
{
	if(argc != 3)
		usage(argv[0]);

	// tcp
	int sockfd;
	sockfd = Socket(AF_INET, SOCK_STREAM, 0);

	struct sockaddr_in srvaddr;
	bzero(&srvaddr, sizeof srvaddr);
	srvaddr.sin_family = AF_INET;
	inet_pton(AF_INET, argv[1],
		(struct sockaddr *)&srvaddr.sin_addr);
	srvaddr.sin_port = htons(atoi(argv[2]));

	Connect(sockfd, (struct sockaddr *)&srvaddr,
				sizeof srvaddr);

	while(1)
	{
		write(sockfd, "123", 3);  //发送普通数据
		sleep(1);

		send(sockfd, "4", 1, MSG_OOB); //MSG_OOB设置为紧急数据
		sleep(1);

		write(sockfd, "56", 2); //发送普通数据
		sleep(1);

		send(sockfd, "78", 2, MSG_OOB); //7是普通数据,8是紧急数据
		sleep(1);
	}
	return 0;
}

接收函数:

#include "head4sock.h"
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <strings.h>
#include <signal.h>

#define MAXSIZE 80

static int connfd;

void usage(const char *info)
{
	printf("Usage: %s <PORT>\n", info);
	exit(0);
}

void catch_sig(int sig)
{
	if(sig == SIGURG)
	{
		char buf[MAXSIZE] = {0};

		recv(connfd, buf, MAXSIZE, MSG_OOB); //读出紧急数据
		printf("urgent data: %s\n", buf);
	}
}

int main(int argc, char **argv)
{
	if(argc != 2)
		usage(argv[0]);

	// tcp
	int sockfd;
	sockfd = Socket(AF_INET, SOCK_STREAM, 0);

	int on = 1;
	Setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on);

	int a = 100;
	Setsockopt(sockfd, SOL_SOCKET, SO_RCVLOWAT, &a, sizeof a); //设置接收缓冲区为100

	struct sockaddr_in srvaddr, cliaddr;
	bzero(&srvaddr, sizeof srvaddr);
	srvaddr.sin_family = AF_INET;
	srvaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	srvaddr.sin_port = htons(atoi(argv[1]));

	Bind(sockfd, (struct sockaddr *)&srvaddr,
		sizeof srvaddr);

	Listen(sockfd, 5);

	socklen_t len;
	char buf[MAXSIZE];

	len = sizeof cliaddr;
	bzero(&cliaddr, len);
	connfd = Accept(sockfd,	(struct sockaddr *)&cliaddr, &len);

	/********************************/
	signal(SIGURG, catch_sig);   //如果有紧急数据来到,则会有信号SIGURG,运行catch_sig
	fcntl(connfd, F_SETOWN, getpid());
	/********************************/

	printf("new connection: %s:%hu\n",
		inet_ntoa(cliaddr.sin_addr),
		ntohs(cliaddr.sin_port));

	int n;
	while(1)
	{
		bzero(buf, MAXSIZE);
		if((n=read(connfd, buf, MAXSIZE)) <= 0)
			break;

		write(STDOUT_FILENO, buf, strlen(buf));
		write(STDOUT_FILENO, "\n", 1);
	}
	return 0;
}

代码运行结果:

在这里插入图片描述

带外数据的主要作用:

  • 从这个实验中可以知道带外数据的大小只能是1字节,因此带外数据并不是用来传送数据的,一般用于传送一些控制信息表示不同的含义。
  • 比如流媒体文件中,大部分信息都为媒体文件信息,但是中间可以包含带外数据(控制信息)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值