Linux下socket通信中的带外数据


简介

在Linux下的socket通信中,带外数据(Out-of-Band,简称OOB)是一种特殊的数据传输方式。通常,socket通信中的数据是按照顺序发送和接收的,即所谓的带内数据(In-Band)。然而,在某些情况下,可能需要发送一些紧急或重要的数据,这些数据不适合通过常规的带内数据传输方式发送,因为它们需要更快速、更直接的传送方式。这时,就可以使用带外数据。

带外数据允许在已经建立的socket连接上发送和接收不在数据流中的信息。这些信息通常用于通知对方某些重要的事件或状态变化,比如连接中断、文件传输中止等。

在Linux系统中,套接字机制支持低层协议发送和接收带外数据。然而,需要注意的是,并非所有的传输层协议都支持带外数据。例如,TCP协议没有真正意义上的带外数据。为了发送重要数据,TCP提供了一种称为紧急模式(Urgent Mode)的机制。在TCP协议中,可以通过设置数据段中的URG位来进入紧急模式。当接收方检测到URG位被设置时,可以采取特殊的处理方式来接收这些紧急数据。

要使用带外数据,可以通过调用send()函数并设置Flags参数为MSG_OOB来发送带外数据。相应地,在接收端,可以通过recv()函数并设置Flags参数为MSG_OOB来接收带外数据。

总之,带外数据是Linux下socket通信中的一种特殊数据传输方式,用于发送和接收不在数据流中的紧急或重要信息。通过带外数据,可以实现更快速、更直接的通知和响应机制。


示例

当使用带外数据时,通常会使用 socket 选项 SO_OOBINLINE 来启用带外数据的发送和接收。下面是一个示例代码,展示了在 Linux 下通过 socket 进行带外数据的发送和接收:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>

void sendOOBData(int socket, const void *data, size_t dataLen)
{
    // 将数据发送为带外数据
    int flags = 0;
    flags |= MSG_OOB;
    ssize_t bytesSent = send(socket, data, dataLen, flags);
    if (bytesSent == -1)
    {
        perror("Failed to send OOB data");
        exit(EXIT_FAILURE);
    }
    printf("Sent %zu bytes of OOB data\n", bytesSent);
}

void receiveOOBData(int socket)
{
    // 接收带外数据
    char oobData[1024];
    ssize_t bytesReceived =recv(socket, oobData, sizeof(oobData), MSG_OOB);
    if (bytesReceived == -1)
    {
        perror("Failed to receive OOB data");
        exit(EXIT_FAILURE);
    }
    printf("Received %zu bytes of OOB data: %s\n", bytesReceived, oobData);
}

int main()
{
    int serverSocket, clientSocket;
    struct sockaddr_in serverAddress, clientAddress;
    socklen_t addressLength = sizeof(clientAddress);

    // 创建一个 TCP socket
    if ((serverSocket = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        perror("Failed to create socket");
        exit(EXIT_FAILURE);
    }

    // 绑定 socket 到本地回环地址和端口 12345
    serverAddress.sin_family = AF_INET;
    serverAddress.sin_addr.s_addr = INADDR_LOOPBACK;
    serverAddress.sin_port = htons(12345);
    if (bind(serverSocket, (struct sockaddr *)&serverAddress, sizeof(serverAddress)) == -1)
    {
        perror("Failed to bind socket");
        exit(EXIT_FAILURE);
    }

    // 开始监听连接
    if (listen(serverSocket, 1) == -1)
    {
        perror("Failed to listen on socket");
        exit(EXIT_FAILURE);
    }

    printf("Waiting for client connection...\n");

    // 接受客户端连接
    if ((clientSocket = accept(serverSocket, (struct sockaddr *)&clientAddress, &addressLength)) == -1)
    {
        perror("Failed to accept connection");
        exit(EXIT_FAILURE);
    }

    printf("Connected with client\n");

    // 发送带外数据
    const char *oobData = "This is OOB data";
    sendOOBData(clientSocket, oobData, strlen(oobData));

    // 接收带外数据
    receiveOOBData(clientSocket);

    // 关闭连接
    close(clientSocket);
    close(serverSocket);

    return 0;
}

在上述示例中,创建了一个 TCP 服务器和一个 TCP 客户端。通过在客户端和服务器之间建立连接,可以使用 socket 选项 SO_OOBINLINE 来启用带外数据的发送和接收。

在服务器端,通过调用 sendOOBData 函数将带外数据发送给客户端。在客户端,通过调用 receiveOOBData 函数来接收带外数据。

请注意,带外数据通常用于在不干扰正常数据传输的情况下传输一些紧急或特殊的数据。在实际应用中,根据需要使用带外数据。

posted @   guanyubo  阅读(211)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示