我正在编写一个Windows上的C++程序,它创建一个原始套接字,将它绑定到一个IPv6接口,并尝试刷新IPv6数据包。不知为什么
recv()
是
在接口上收到(我使用Wireshark进行了验证)。
这是我写的代码:
#include <stdio.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <string>
#include "IpUtils.h"
#define SIO_RCVALL 0x98000001
#define RAW_SOCKET_BUFFER_LEN 65536
int main()
{
int timeout = 10; // 10 seconds
std::string ipv6Addr = "my IPv6 address...";
int numOfPackets = 1; // try to read just one packet
WSADATA wsaData;
WSAStartup(MAKEWORD(2,2), &wsaData);
SOCKET fd = socket(AF_INET6, SOCK_RAW, IPPROTO_IPV6);
if (fd < 0)
{
printf("error in socket creation\n");
return 1;
}
else
printf("socket creation succeeded\n");
struct sockaddr_in6 localAddrIPv6;
localAddrIPv6.sin6_family = AF_INET6;
inet_pton(AF_INET6, ipv6Addr.c_str(), &localAddrIPv6.sin6_addr.s6_addr);
localAddrIPv6.sin6_port = 0; // Any local port will do
localAddrIPv6.sin6_scope_id = 0;
if (bind(fd, (struct sockaddr *)&localAddrIPv6, sizeof(localAddrIPv6)) < 0)
{
printf("error in bind, error code was %d\n", WSAGetLastError());
closesocket(fd);
return 1;
}
else
printf("bind succeeded\n");
int n = 1;
DWORD dwBytesRet;
if (WSAIoctl(fd, SIO_RCVALL, &n, sizeof(n), NULL, 0, &dwBytesRet, NULL, NULL) == SOCKET_ERROR)
{
printf("Call to WSAIotcl(%ul) failed with error code %d\n", SIO_RCVALL, WSAGetLastError());
closesocket(fd);
return 1;
}
else
printf("call to WSAIotcl succeeded\n");
DWORD timeoutVal = timeout * 1000;
setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeoutVal, sizeof(timeoutVal));
for (int i = 0; i < numOfPackets; i++)
{
char* buffer = new char[RAW_SOCKET_BUFFER_LEN];
memset(buffer, 0, RAW_SOCKET_BUFFER_LEN);
printf("start recv for packet #%d\n", i);
int bufferLen = recv(fd, buffer, RAW_SOCKET_BUFFER_LEN, 0);
if (bufferLen < 0)
{
printf("recv failed with an error code %d\n", WSAGetLastError());
closesocket(fd);
delete [] buffer;
return 1;
}
else
{
printf("Got a packet with len %d\n", bufferLen);
}
delete [] buffer;
}
return 0;
}
IpUtils.h
包含的Windows实现
inet_pton()
如[此处][1]所述。
我使用的编译器是MinGW/MinGW-w64。
另外,下面是我正在使用的makefile:
# All Target
all:
g++.exe -c -o IpUtils.o IpUtils.cpp
g++.exe -c -o main.o main.cpp
g++.exe -o test.exe main.o IpUtils.o -lws2_32
# Clean Target
clean:
del main.o
del IpUtils.o
del test.exe
运行程序后得到的输出是:
socket creation succeeded
bind succeeded
call to WSAIotcl succeeded
start recv for packet #0
recv failed with an error code 10060 <== WSAETIMEDOUT which means timeout expired
编辑:
根据下面的评论,我设法通过替换行来查看IPv6流量
SOCKET fd = socket(AF_INET6, SOCK_RAW, IPPROTO_IPV6)
具有
SOCKET fd = socket(AF_INET6, SOCK_RAW, IPPROTO_IP)
Remy Lebeau's comment below
). 所以我现在的问题是如何知道我得到的有效载荷的协议?通常IPv6头中会提到有效负载协议,但是由于我没有它,我如何知道/猜测它?