Unix网络编程-TCP带外数据(紧急数据)

简单的发送程序

/**
 * @file oobtcpsend1.c
 * 简单的带外数据发送程序
 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>

int get_sock_connet(char *ip, int port)
{
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        perror("socket");
        exit(-1);
    }

    struct sockaddr_in serveraddr;
    bzero(&serveraddr, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(port);
    inet_pton(AF_INET, ip, &serveraddr.sin_addr.s_addr);

    if (connect(sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) < 0)
    {
        perror("connect");
        exit(-1);
    }

    return sockfd;
}

int main(int argc, char **argv)
{
    if (argc < 2)
    {
        fprintf(stderr, "Using error: ./process.c [ip] [port] \n");
        exit(-1);
    }
    int sockfd = get_sock_connet(argv[1], atoi(argv[2]));
    
    write(sockfd, "123", 3);
    printf("write 3 bytes of normal data.\n");
    sleep(1);

    send(sockfd, "4", 1, MSG_OOB);
    printf("send 1 byte of OOB data.\n");
    sleep(1);

    write(sockfd, "56", 2);
    printf("write 2 bytes of normal data.\n");
    sleep(1);

    send(sockfd, "7", 1, MSG_OOB);
    printf("send 1 byte of OOB data.\n");
    sleep(1);

    write(sockfd, "89", 2);
    printf("write 2 bytes of normal data.\n");
    sleep(1);

    exit(0);
}

简单的接收程序

/**
 * @file oobtcprecv1.c
 * 简单的带外数据的接收程序
 */
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <signal.h>
#define ADDRESS "127.0.0.1"
#define PORT 1226

int sockfd;

int set_listen_accept(char *ip, int port)
{
    int listensockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (listensockfd < 0)
    {
        perror("socket");
        exit(-1);
    }

    struct sockaddr_in serveraddr;
    bzero(&serveraddr, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(port);
    inet_pton(AF_INET, ip, &serveraddr.sin_addr.s_addr);

    if (bind(listensockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) < 0)
    {
        perror("bind");
        exit(-1);
    }

    if (listen(listensockfd, 20) < 0)
    {
        perror("listen");
        exit(-1);
    }

    int connsock = accept(listensockfd, NULL, NULL);
    if (connsock < 0)
    {
        perror("accept");
        exit(-1);
    }

    return connsock;
}

// SIGURG信号处理函数
void sig_urg(int signo)
{
    int n;
    char buf[100];
    bzero(buf, 100);
    printf("SIGURG received.\n");
    n = recv(sockfd, buf, 100, MSG_OOB);
    printf("read %d OOB byte: %s.\n", n, buf);
}

int main(int argc, char **argv)
{
    if (argc < 2)
    {
        fprintf(stderr, "Using error: ./process.c [ip] [port] \n");
        exit(-1);
    }

    sockfd = set_listen_accept(argv[1], atoi(argv[2]));

    signal(SIGURG, sig_urg);    // 注册信号处理函数

    fcntl(sockfd, F_SETOWN, getpid());  // 设置套接字的从属为当前进程

    int n;
    char buf[100];
    while (1)
    {
        bzero(buf, 100);
        if ((n = read(sockfd, buf, 100)) == 0)
        {
            printf("recvived EOF.\n");
            exit(0);
        }
        printf("read %d bytes:%s.\n", n, buf);
    }

    exit(0);
}

使用select代替信号的不正确版本

/**
 * @file oobtcprecv2.c
 * 使用select的不正确版本
 */
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <signal.h>
#include <sys/select.h>
int sockfd;

int set_listen_accept(char *ip, int port)
{
    int listensockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (listensockfd < 0)
    {
        perror("socket");
        exit(-1);
    }

    struct sockaddr_in serveraddr;
    bzero(&serveraddr, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(port);
    inet_pton(AF_INET, ip, &serveraddr.sin_addr.s_addr);

    if (bind(listensockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) < 0)
    {
        perror("bind");
        exit(-1);
    }

    if (listen(listensockfd, 20) < 0)
    {
        perror("listen");
        exit(-1);
    }

    int connsock = accept(listensockfd, NULL, NULL);
    if (connsock < 0)
    {
        perror("accept");
        exit(-1);
    }

    return connsock;
}

int main(int argc, char **argv)
{
    if (argc < 2)
    {
        fprintf(stderr, "Using error: ./process.c [ip] [port] \n");
        exit(-1);
    }

    sockfd = set_listen_accept(argv[1], atoi(argv[2]));

    fd_set rset, xset;
    FD_ZERO(&rset);
    FD_ZERO(&xset);
    while (1)
    {
        FD_SET(sockfd, &rset);
        FD_SET(sockfd, &xset);

        select(sockfd + 1, &rset, NULL, &xset, NULL);

        if (FD_ISSET(sockfd, &xset))
        {
            char buf[100];
            bzero(buf, 100);
            int n = recv(sockfd, buf, 100, MSG_OOB);
            printf("read %d OOB byte: %s\n", n, buf);
        }
        if (FD_ISSET(sockfd, &rset))
        {
            char buf[100];
            bzero(buf, 100);
            int n = read(sockfd, buf, 100);
            if (n == 0)
            {
                printf("read EOF\n");
                exit(0);
            }
            printf("read %d bytes: %s\n", n, buf);
        }
    }
}

使用select代替信号的正确版本

/**
 * @file oobtcprecv3.c
 * 使用select的正确版本
 */
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <signal.h>
#include <sys/select.h>
int sockfd;

int set_listen_accept(char *ip, int port)
{
    int listensockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (listensockfd < 0)
    {
        perror("socket");
        exit(-1);
    }

    struct sockaddr_in serveraddr;
    bzero(&serveraddr, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(port);
    inet_pton(AF_INET, ip, &serveraddr.sin_addr.s_addr);

    if (bind(listensockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) < 0)
    {
        perror("bind");
        exit(-1);
    }

    if (listen(listensockfd, 20) < 0)
    {
        perror("listen");
        exit(-1);
    }

    int connsock = accept(listensockfd, NULL, NULL);
    if (connsock < 0)
    {
        perror("accept");
        exit(-1);
    }

    return connsock;
}

int main(int argc, char **argv)
{
    if (argc < 2)
    {
        fprintf(stderr, "Using error: ./process.c [ip] [port] \n");
        exit(-1);
    }

    sockfd = set_listen_accept(argv[1], atoi(argv[2]));

    fd_set rset, xset;
    int justreadoob = 0;
    FD_ZERO(&rset);
    FD_ZERO(&xset);
    while (1)
    {
        FD_SET(sockfd, &rset);
        if (justreadoob == 0)
        {
            FD_SET(sockfd, &xset);
        }
        

        select(sockfd + 1, &rset, NULL, &xset, NULL);

        if (FD_ISSET(sockfd, &xset))
        {
            char buf[100];
            bzero(buf, 100);
            int n = recv(sockfd, buf, 100, MSG_OOB);
            printf("read %d OOB byte: %s\n", n, buf);
            justreadoob = 1;
            FD_CLR(sockfd, &xset);
        }
        if (FD_ISSET(sockfd, &rset))
        {
            char buf[100];
            bzero(buf, 100);
            int n = read(sockfd, buf, 100);
            if (n == 0)
            {
                printf("read EOF\n");
                exit(0);
            }
            printf("read %d bytes: %s\n", n, buf);
            justreadoob = 0;
        }
    }
}

使用sockatmark()函数定位带外标志

/**
 * @file oobtcprecv4.c
 * 使用带外标记
 */
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <signal.h>
#include <sys/select.h>
int set_listen_accept(char *ip, int port)
{
    int listensockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (listensockfd < 0)
    {
        perror("socket");
        exit(-1);
    }

    struct sockaddr_in serveraddr;
    bzero(&serveraddr, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(port);
    inet_pton(AF_INET, ip, &serveraddr.sin_addr.s_addr);

    if (bind(listensockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) < 0)
    {
        perror("bind");
        exit(-1);
    }

    if (listen(listensockfd, 20) < 0)
    {
        perror("listen");
        exit(-1);
    }

    int connsock = accept(listensockfd, NULL, NULL);
    if (connsock < 0)
    {
        perror("accept");
        exit(-1);
    }

    return connsock;
}

int main(int argc, char **argv)
{
    if (argc < 2)
    {
        fprintf(stderr, "Using error: ./process.c [ip] [port] \n");
        exit(-1);
    }

    int sockfd = set_listen_accept(argv[1], atoi(argv[2]));

    int on = 1;
    setsockopt(sockfd, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on));  // 打开在线数据

    // 等待数据发送完毕
    // 这样带外数据和普通数据都在一个缓冲区里
    sleep(5);

    while (1)
    {
        if (sockatmark(sockfd))
        {
            printf("at OOB mark\n");
        }
        int n;
        char buf[100];
        bzero(buf, 100);
        if ((n = read(sockfd, buf, 100)) == 0)
        {
            printf("read EOF\n");
            exit(0);
        }
        printf("read %d bytes: %s\n", n, buf);
    }
    exit(0);
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

橙子砰砰枪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值