简单说明
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;
}