TCP带外数据

简单说明

TCP带外数据也称为紧急模式, 常用于中断某些操作, 如中断ftp文件的传输.
调用系统函数时我们需要处理一些信号操作, 而TCP带外数据可理解为由本地向对端发送一个signal, 让对端能采取相应的处理措施.
接收到带外数据时, 系统会产生SIGURG信号.
TCP带外数据就是一个普通的字节, 只是在TCP头部特别注明在哪个位置的字节是带外数据而已.

TCP带外数据的格式要求:

  • 每个连接只有一个TCP带外数据
  • 每个连接只有一个带外标记
  • 每个连接只有一个单字节的带外缓冲区

通俗的讲就是在TCP接受缓冲区内一次只能有一个带外数据存在, 不能同时存在二个或多个, 且每个带外数据只有一个字节

简单发送与接受

send.c

注意send(sockfd,"444",3,MSG_OOB), 虽然发送了三个字节的紧张数据, 实际有效的只有一位

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <unistd.h>
#include <strings.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>

#define SERV_PORT 5555

int tcp_connect(){
    struct sockaddr_in serv;
    int sockfd;

    sockfd=socket(AF_INET,SOCK_STREAM,0);
    assert(sockfd);
    bzero(&serv,sizeof(serv));
    serv.sin_family=AF_INET;
    serv.sin_port=htons(SERV_PORT);
    serv.sin_addr.s_addr=inet_addr("127.0.0.1");

    assert(connect(sockfd,(struct sockaddr *)&serv,sizeof(serv)) == 0);
    return sockfd;
}

int main(int argc, char *argv[]) {
    int sockfd=tcp_connect();
    write(sockfd,"123",3);
    printf("wrote 3 bytes of normal data
");
    sleep(1);

    send(sockfd,"444",3,MSG_OOB);
    printf("wrote 3 byte of OOB data
");
    sleep(1);

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

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

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

    return 0;
    return 0;
}

recv.c

通过设置fcntl来请求系统将SIGURG信号发送给指定进程

#include <stdio.h>
#include <fcntl.h>
#include <signal.h>
#include <assert.h>
#include <stdlib.h>
#include <unistd.h>
#include <strings.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>

#define SERV_PORT 5555

int sockfd,connfd;

int tcp_listen(){
    struct sockaddr_in serv;
    int sockfd;

    sockfd=socket(AF_INET,SOCK_STREAM,0);
    assert(sockfd);
    bzero(&serv,sizeof(serv));
    serv.sin_family=AF_INET;
    serv.sin_port=htons(SERV_PORT);
    serv.sin_addr.s_addr=inet_addr("127.0.0.1");

    assert(bind(sockfd,(struct sockaddr *)&serv,sizeof(serv)) == 0);
    assert(listen(sockfd,10) == 0);
    return sockfd;
}

void sig_urg(int signo){
    int n;
    char buff[10];

    printf("SIGURG received
");
    n=recv(connfd,buff,sizeof(buff)-1,MSG_OOB);
    buff[n]=0;
    printf("read %d OOB bytes: %s
",n,buff);
}

int main(int argc, char *argv[]) {
    sockfd=tcp_listen();
    connfd=accept(sockfd,NULL,NULL);

    signal(SIGURG,sig_urg);
    fcntl(connfd,F_SETOWN,getpid());

    int n;
    char buff[100];
    for(;;){
        if((n=read(connfd,buff,sizeof(buff)-1)) == 0){
            printf("received EOF
");
            exit(0);
        }
        buff[n]=0;
        printf("read %d bytes: %s
",n,buff);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/cfans1993/p/6598327.html