服务器端 testnet
#include <iostream>
using namespace std;
#include<signal.h>
#include<assert.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<unistd.h>
#include<errno.h>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define BUF_SIZE 1024
int main(int argc,char * argv[])
{
if(argc<=2)
{
printf("usage:%s ip_address port_number\n",basename(argv[0]) );
return 1;
}
const char * ip=argv[1];
int port=atoi(argv[2]);
struct sockaddr_in server_address;
bzero(&server_address,sizeof(server_address));
server_address.sin_family=AF_INET;
inet_pton(AF_INET,ip,&server_address.sin_addr);//在点分地址和二进制地址之间转换,第二个参数是点分地址,第三个参数是二进制整数
server_address.sin_port=htons(port);//主机字节序转换为网络字节序
int sockfd=socket(PF_INET,SOCK_STREAM,0);//1
assert(sockfd>=0);
int ret=bind(sockfd,(struct sockaddr*)&server_address,sizeof(server_address));//2
assert(ret!=-1);
ret=listen(sockfd,5);
assert(ret!=-1);
struct sockaddr_in client;
socklen_t client_addrlength=sizeof(client);
int connfd=accept(sockfd,(struct sockaddr*)&client,&client_addrlength);
if(connfd<0)
printf("errno is :%d\n",errno);
else
{
char buffer[BUF_SIZE];
memset(buffer,'\0',BUF_SIZE);
ret =recv(connfd,buffer,BUF_SIZE-1,0);
printf("got %d bytes of normal data: '%s'\n",ret,buffer);
memset(buffer,'\0',BUF_SIZE);
ret =recv(connfd,buffer,BUF_SIZE-1,MSG_OOB);
printf("got %d bytes of oob data: '%s'\n",ret,buffer);
memset(buffer,'\0',BUF_SIZE);
ret =recv(connfd,buffer,BUF_SIZE-1,0);
printf("got %d bytes of normal data: '%s'\n",ret,buffer);
}
close(sockfd);
return 0;
}
客户端 testcplus
#include<signal.h>
#include<assert.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<unistd.h>
#include<errno.h>
int main(int argc,char * argv[])
{
if(argc<=2)
{
printf("usage:%s ip_address port_number\n",basename(argv[0]) );
return 1;
}
const char * ip=argv[1];
int port=atoi(argv[2]);
struct sockaddr_in server_address;
bzero(&server_address,sizeof(server_address));
server_address.sin_family=AF_INET;
inet_pton(AF_INET,ip,&server_address.sin_addr);//在点分地址和二进制地址之间转换,第二个参数是点分地址,第三个参数是二进制整数
server_address.sin_port=htons(port);//主机字节序转换为网络字节序
int sockfd=socket(PF_INET,SOCK_STREAM,0);
assert(sockfd>=0);
if(connect(sockfd,(struct sockaddr*)&server_address,sizeof(server_address))<0)
{
printf("connection failed\n");
}else
{
const char * oob_data="abc";
const char * normal_data="123";
send(sockfd,normal_data,strlen(normal_data),0);
send(sockfd,oob_data,strlen(oob_data),MSG_OOB);
send(sockfd,normal_data,strlen(normal_data),0);
}
close(sockfd);
return 0;
}
./testcplus 172.18.216.66 55555
./testnet 172.18.216.66 55555
tcpdump -ntx -i eth0 port 55555
实验得知,在带外数据abc中,仅有最后一个字符c被服务器当成真正的带外数据接收。服务器的正常数据的接收将被带外数据截断。
flag参数只对send和recv的当前调用有效。