Я писал утилиту для проверки / proc / net / tcp и tcp6 на наличие активных соединений, поскольку она быстрее, чем анализ вывода netstat.
Поскольку на самом деле у меня не включен ipv6, я в основном использовал localhost в качестве ориентира. Вот копия моего / proc / net / tcp6
sl local_address remote_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
0: 00000000000000000000000000000000:006F 00000000000000000000000000000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 19587 1 ffff880262630000 100 0 0 10 -1
1: 00000000000000000000000000000000:0050 00000000000000000000000000000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 22011 1 ffff880261c887c0 100 0 0 10 -1
2: 00000000000000000000000000000000:0016 00000000000000000000000000000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 21958 1 ffff880261c88000 100 0 0 10 -1
3: 00000000000000000000000001000000:0277 00000000000000000000000000000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 28592 1 ffff88024eea0000 100 0 0 10 -1
Вот соответствующий netstat -6 -pant
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp6 0 0 :::111 :::* LISTEN -
tcp6 0 0 :::80 :::* LISTEN -
tcp6 0 0 :::22 :::* LISTEN -
tcp6 0 0 ::1:631 :::* LISTEN -
Записи 0–3 из tcp6 соответствуют :: (все ipv6), но запись 4 предположительно является соответствующей записью для :: 1.
Вот где я запутался ...
00000000000000000000000001000000 => 0000: 0000: 0000: 0000: 0000: 0000: 0100: 0000 => :: 100: 0
Когда я запускаю :: 1 через какой-то код для генерации полного шестнадцатеричного представления, я получаю:
import binascii
import socket
print binascii.hexlify(socket.inet_pton(socket.AF_INET6, '::1'))
00000000000000000000000000000001
Я не могу программно выровнять эти два значения, потому что они не совпадают (очевидно). Почему они не совпадают? Почему ядро считает, что :: 100: 0 равно :: 1?
Это связано с противоречивым порядком байтов в /proc/net/tcp6
. Адрес обрабатывается как четыре слова, состоящее из четырех байтов каждое. В каждом из этих четырех слов четыре байта записываются в обратном порядке.
2001:0db8 :: 0123:4567:89ab:cdef would thus come out as:
B80D 0120 00000000 6745 2301 EFCD AB89 (with spaces inserted for clarity).
Вероятно, это связано с различиями в порядке байтов. Большинство компьютеров в наши дни используют IA32 или AMD64, которые используют порядок байтов, противоположный тому, с которым был разработан IP. У меня нет других систем для тестирования, чтобы понять, можно ли полагаться на / proc / net / tcp6, который всегда выглядит так. Но я подтвердил, что это справедливо как для архитектуры IA32, так и для AMD64.
Нашел этот модуль perl, предназначенный для разбора / proc / net / tcp http://search.cpan.org/~salva/Linux-Proc-Net-TCP-0.05/lib/Linux/Proc/Net/TCP.pm Он цитирует документацию ядра, как показано ниже.
This document describes the interfaces /proc/net/tcp and
/proc/net/tcp6. Note that these interfaces are deprecated in favor
of tcp_diag.
These /proc interfaces provide information about currently active TCP
connections, and are implemented by tcp4_seq_show() in
net/ipv4/tcp_ipv4.c and tcp6_seq_show() in net/ipv6/tcp_ipv6.c,
respectively.
It will first list all listening TCP sockets, and next list all
established TCP connections. A typical entry of /proc/net/tcp would
look like this (split up into 3 parts because of the length of the
line):
46: 010310AC:9C4C 030310AC:1770 01
| | | | | |--> connection state
| | | | |------> remote TCP port number
| | | |-------------> remote IPv4 address
| | |--------------------> local TCP port number
| |---------------------------> local IPv4 address
|----------------------------------> number of entry
00000150:00000000 01:00000019 00000000
| | | | |--> number of unrecovered RTO timeouts
| | | |----------> number of jiffies until timer expires
| | |----------------> timer_active (see below)
| |----------------------> receive-queue
|-------------------------------> transmit-queue
1000 0 54165785 4 cd1e6040 25 4 27 3 -1
| | | | | | | | | |--> slow start size threshold,
| | | | | | | | | or -1 if the threshold
| | | | | | | | | is >= 0xFFFF
| | | | | | | | |----> sending congestion window
| | | | | | | |-------> (ack.quick<<1)|ack.pingpong
| | | | | | |---------> Predicted tick of soft clock
| | | | | | (delayed ACK control data)
| | | | | |------------> retransmit timeout
| | | | |------------------> location of socket in memory
| | | |-----------------------> socket reference count
| | |-----------------------------> inode
| |----------------------------------> unanswered 0-window probes
|---------------------------------------------> uid
timer_active:
0 no timer is pending
1 retransmit-timer is pending
2 another timer (e.g. delayed ack or keepalive) is pending
3 this is a socket in TIME_WAIT state. Not all fields will contain
data (or even exist)
4 zero window probe timer is pending
Я анализирую / proc / net / tcp, а также / tcp6, / udp6 на Android, и это мои простые методы преобразования на Java. Спасибо kasperd за то, что помог мне найти это решение.
/**B80D01200000000067452301EFCDAB89 -> 2001:0db8:0000:0000:0123:4567:89ab:cdef
* */
public static String toRegularHexa(String hexaIP){
StringBuilder result = new StringBuilder();
for(int i=0;i<hexaIP.length();i=i+8){
String word = hexaIP.substring(i,i+8);
for (int j = word.length() - 1; j >= 0; j = j - 2) {
result.append(word.substring(j - 1, j + 1));
result.append((j==5)?":":"");//in the middle
}
result.append(":");
}
return result.substring(0,result.length()-1).toString();
}
/**0100A8C0 -> 192.168.0.1*/
public static String hexa2decIPv4 (String hexa) {
StringBuilder result = new StringBuilder();
//reverse Little to Big
for (int i = hexa.length() - 1; i >= 0; i = i - 2) {
String wtf = hexa.substring(i - 1, i + 1);
result.append(Integer.parseInt(wtf, 16));
result.append(".");
}
//remove last ".";
return result.substring(0,result.length()-1).toString();
}
/**0000000000000000FFFF00008370E736 -> 0.0.0.0.0.0.0.0.0.0.255.255.54.231.112.131
0100A8C0 -> 192.168.0.1
*/
public static String hexa2decIP (String hexa) {
StringBuilder result = new StringBuilder();
if(hexa.length()==32){
for(int i=0;i<hexa.length();i=i+8){
result.append(hexa2decIPv4(hexa.substring(i, i + 8)));
result.append(".");
}
}else {
if(hexa.length()!=8){return "0.0.0.0";}
return hexa2decIPv4(hexa);
}
//remove last ".";
return result.substring(0,result.length()-1).toString();
}
/**Simple hexa to dec, for ports
* 01BB -> 403
* */
public static String hexa2decPort(String hexa) {
StringBuilder result = new StringBuilder();
result.append(Integer.parseInt(hexa, 16));
return result.toString();
}