首先,我对 IPv6 的细节还不熟悉,所以如果这只是对 IPv6 路由的误解,我不会感到惊讶。考虑一下我正在运行 P2P 覆盖网络的情况,其中一部分位于单个 LAN 的边界内。该 LAN 内的节点具有以下链路本地地址(如其自身所见):
现在,假设每个对等点都能够通过某种方式发现其他对等点,并拥有彼此的地址。每个对等点都在侦听一个端口,例如 12345。如果对等点 1 想与对等点 2 通信,他们可能会尝试使用 URI:
tcp://[fe80:225:4bff:fea8:e201%eth1]:12345
这就是我遇到问题的地方。对等点 1 没有名为“eth1”的适配器,因此它不知道该 IPv6 区域标识符。如果从地址中删除区域 ID,则对等体 1 无法确定必须使用哪个适配器来联系主机。
那么问题来了:是否有可能以标准方式解析 IPv6 地址的区域标识符?如果没有,我是否必须向系统查询所有区域标识符,并尝试依次使用每个区域标识符连接到该地址,直到成功为止?或者尝试使用链接本地地址进行通信从一开始就是一个愚蠢的想法?
MAC 地址用于唯一标识我的计算机。IP 地址用于将数据包路由到网络,因为它具有层次结构,但它不唯一标识计算机。那么,在IPv6之后,每台计算机都会有一个唯一的IP地址,那么MAC地址还有必要吗?如果我理解错了,请纠正我。
我有一个简单的客户端服务器程序和服务器端工作,但由于某种原因,我无法让客户端与服务器进行交互.我能够启动服务器并使用nc -u ::1 50007并连接到它,它按预期工作.
服务器代码:
import socket
import sys
def main():
HOST = '::1'
PORT = 50007
res = socket.getaddrinfo(HOST, PORT, socket.AF_UNSPEC, socket.SOCK_STREAM, 0, socket.AI_PASSIVE)
af, socktype, proto, canonname, sa = res[0]
try:
s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
s.bind(sa)
while True:
data, addr = s.recvfrom(1024)
if not data:
break
print 'server received %r from %r' % (data, addr)
s.sendto(data, addr)
s.close()
except socket.error, msg:
print msg
if __name__ == '__main__':
main()
Run Code Online (Sandbox Code Playgroud)
客户代码:
import socket
import sys
def main():
HOST …Run Code Online (Sandbox Code Playgroud) 我有一些代码通过预先创建套接字(通过.socket()BSD API)工作,然后在地址已知的时候它将执行connect()等.这适用于IPv4但现在我正在重构也支持IPv6.
问题是,当我执行初始socket()时,我需要放入AF_INET或AF_INET6.但是因为我不知道地址但我不知道哪个是正确的.反正有没有创建一个适用于任何一个的通用套接字?如果我使用AF_INET6并且我在IPv4网络上,我是否正确认为它不起作用?
一个相关的问题 - 即使我还不知道IP地址,我是否有可能检测到我的设备所处的网络:IPv4还是IPv6?假设有一个网络接口,我想我只能是其中一个网络,所以如果我能找到一种方法来检测我的设备所处的网络类型,那么我可以在创建套接字时这样做.
另一个选择是重构只有在我知道地址时才创建套接字,但是有一个很大的代码库,如果可能的话我想避免这种情况.
我正在编写在iOS上运行的代码,但我不确定这是否与此相关.
当我尝试 ping6 我的 VirtualBox 机器时,出现以下错误:
$ ping6 fe80::a00:27ff:fe1e:42d9
connect: Invalid argument
Run Code Online (Sandbox Code Playgroud)
当然,我已经用谷歌搜索过,发现我可以通过将接口名称附加到该 IPv6 地址本身来避免这种情况 - 事实上,它工作正常:
$ ping6 fe80::a00:27ff:fe1e:42d9%vboxnet0
PING fe80::a00:27ff:fe1e:42d9%vboxnet0(fe80::a00:27ff:fe1e:42d9) 56 data bytes
64 bytes from fe80::a00:27ff:fe1e:42d9: icmp_seq=1 ttl=64 time=0.239 ms
64 bytes from fe80::a00:27ff:fe1e:42d9: icmp_seq=2 ttl=64 time=0.272 ms
64 bytes from fe80::a00:27ff:fe1e:42d9: icmp_seq=3 ttl=64 time=0.283 ms
Run Code Online (Sandbox Code Playgroud)
但是,我对此感到不舒服。我该怎么做才能使它在本地网络中像“ping6 fe80::a00:27ff:fe1e:42d9”一样工作?
我不明白为什么getaddrinfo不返回有效的IPv6地址.
在我的系统上,下面的代码是打印22:B8:00:00:00:00:00:00:00:00:00:00:00:00,但我期望在01某个地方,因为localhost应该解决::1.
同时,sa_data只有14个字节,而IPv6地址是16个字节,所以似乎最后几个字节总是被切断,并且该函数不能返回IPv6地址?
有人可以解释发生了什么吗?我该如何在IPv6中使用此功能?
#include <stdio.h>
#include <WinSock2.h>
#include <WS2TCPIP.h>
#pragma comment(lib, "WS2_32")
int main(int argc, char *argv[])
{
WSADATA wsadata;
WSAStartup(0x0002, &wsadata);
addrinfo addr_hints = { 0, PF_INET6, SOCK_DGRAM, IPPROTO_UDP }, *addrs_out;
getaddrinfo("localhost", "8888", &addr_hints, &addrs_out);
fprintf(stderr,
"%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
static_cast<unsigned char>(addrs_out->ai_addr->sa_data[ 0]),
static_cast<unsigned char>(addrs_out->ai_addr->sa_data[ 1]),
static_cast<unsigned char>(addrs_out->ai_addr->sa_data[ 2]),
static_cast<unsigned char>(addrs_out->ai_addr->sa_data[ 3]),
static_cast<unsigned char>(addrs_out->ai_addr->sa_data[ 4]),
static_cast<unsigned char>(addrs_out->ai_addr->sa_data[ 5]),
static_cast<unsigned char>(addrs_out->ai_addr->sa_data[ 6]),
static_cast<unsigned char>(addrs_out->ai_addr->sa_data[ 7]),
static_cast<unsigned char>(addrs_out->ai_addr->sa_data[ 8]), …Run Code Online (Sandbox Code Playgroud) 一些完全有效的IPv6地址被net.ParseIP()视为IPv4,例如0000:0000:0000:0000:0000:ffff:0100:0000/:: ffff:0100:0.(有关简单示例,请参阅https://play.golang.org/p/57jAJVSIrHF)
处理这种情况最常用的方法是什么?网络包不会导出大部分功能,因此重写net.Parse会导致大量代码重复.
预先感谢您的帮助!
最好的祝福,
斯特凡
我正在开展一个需要扩展 IPv6 地址的项目。Go中有内置函数吗?
我目前正在做的是
ipv6 := "fe80:01::af0"
addr := net.ParseIP(ipv6)
fmt.Println(addr.String())
Run Code Online (Sandbox Code Playgroud)
但这仍然打印
fe80:01::af0
Run Code Online (Sandbox Code Playgroud)
我真正需要的是
fe80:0001:0000:0000:0000:0000:0000:0af0
Run Code Online (Sandbox Code Playgroud) 我正在尝试在 Ubuntu 18.04 和 Ubuntu 20.04 上使用 pip 安装一个包(任何包)。但是,我最终得到以下错误消息:
$ pip install --upgrade pip
WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None))
after connection broken by 'ReadTimeoutError("HTTPSConnectionPool(host='pypi.org', port=443):
Read timed out. (read timeout=15)")': /simple/pip/
...
Run Code Online (Sandbox Code Playgroud)
这是我尝试过的,但没有奏效:
我的系统是 macOS,我尝试使用/sbin/route配置一些自定义路由,我知道0.0.0.0是默认的 ipv4 路由,因此我可以通过运行来删除/更改/添加默认的 ipv4 路由route delete 0.0.0.0。
然后搜了wiki发现ipv6的默认路由地址是::or ,我尝试运行or::/0删除路由,结果返回。route delete ::route delete ::/0route: bad address: ::
我的ipv6路由表是:
Internet6:
Destination Gateway Flags Netif Expire
default fe80::3600:a3ff:fed3:93e5%en0 UGcI en0
default fe80::%utun0 UGcI utun0
::1 ::1 UHL lo0
Run Code Online (Sandbox Code Playgroud)
问题是该default值是什么以及如何更改它?