Форум программистов, компьютерный форум, киберфорум
Java: Сети
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
0 / 0 / 0
Регистрация: 29.09.2011
Сообщений: 18
1

DatagramSocket.receive() не видит входящий пакет

26.04.2013, 05:55. Показов 1407. Ответов 0
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Задача:
Опрос NetBIOS и DNS имени сетевого узла по его IP адресу. При недоступности узла или при отсутствии реализации NBT протокола на сетевом узле возвращает пустую строчку.

Средства:
Книга "Защита от взлома. Сокеты, shell-код, эксплойты_Джеймс С. Фостер_2006", глава 5, пример 5.8 - программа NBTSTAT на языке Java.

Код:
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
import java.io.IOException;
import java.net.*;
 
public class NetBIOSNameThread extends Thread{
    
    HostNetInfo hninfo = null;
    DatagramSocket ds = null;
    DatagramPacket dpqry = null;
    DatagramPacket dprsp = null;
    InetAddress ia = null;
    byte NetBIOSNameCp866[] = null;
    byte[] brsp = new byte[0xFFFF];
    static byte[] bqry = new byte[]{
        // NetBIOS over TCP/IP (NBT) name service query
        (byte) 0x81, (byte) 0xd4, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x20, 0x43, 0x4b, 0x41, 0x41, 0x41,
        0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 
        0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 
        0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 
        0x41, 0x41, 0x41, 0x00, 0x00, 0x21, 0x00, 0x01
        };
    private static String good_literals = "АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяЁёЄєЇїЎўABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789%-._";
 
    
    NetBIOSNameThread(HostNetInfo hni){
        hninfo = hni;
        }
    
    @Override
    public void run(){
        this.hninfo.setNetBIOSName(this.NetBIOSName().toLowerCase());
        
//        String rez_nbn = "";
//        String[] str_arr = new String[3];
//        for (int i = 0; i < 3; i++){
//            ds = null;
//            dpqry = null;
//            dprsp = null;
//            NetBIOSNameCp866 = null;
//            brsp = new byte[0xFFFF];
//            str_arr[i] = this.NetBIOSName().toLowerCase();
//            if (!"".equals(str_arr[i])) rez_nbn = str_arr[i];
//            }
//        this.hninfo.setNetBIOSName(rez_nbn);
        
        InetAddress addr = null;
        try {
            addr = InetAddress.getByName(this.hninfo.getIP());
            } 
        catch (UnknownHostException ex) {
            System.out.println("Ошибка определения DNS имени по IP адресу" + this.hninfo.getIP());
            }
        String tmpStr = addr.getHostName();
        if (!tmpStr.equals(this.hninfo.getIP())){
            int dotIndex = tmpStr.indexOf('.');
            if (dotIndex > 0){
                tmpStr = tmpStr.substring(0, tmpStr.indexOf('.'));
                this.hninfo.setDNSName(tmpStr.toLowerCase());
                }
            else this.hninfo.setDNSName(tmpStr.toLowerCase());
            }
        }
    
    private static boolean correct_nbname(String nbname){
        boolean tmp = true;
        for (int i = 0; i < nbname.length(); i++){
            tmp &= good_literals.contains(nbname.subSequence(i, i + 1));
            }
        return tmp;
        }
    
    private boolean can_read(int a, int b){
        boolean good_length = dprsp.getData().length > (b + 1);
        boolean good_record_type_a = (dprsp.getData()[a] == 0);
        boolean good_record_type_b = (dprsp.getData()[b] == 4)||(dprsp.getData()[b] == 6);
        return good_length && good_record_type_a && good_record_type_b;
        }
    
    private String NetBIOSName(){
        if ("".equals(this.hninfo.getIP())) return "";
        try{
            ia = InetAddress.getByName(this.hninfo.getIP());
            
            SocketAddress sa = new InetSocketAddress(this.hninfo.getIP(), 137);
 
 
            // Создаем UDP сокет
            ds = new DatagramSocket();
            // Определяем таймаут ожидания ответа для сокета
            // Если параметр не определить, то поток 
            // бесконечно ожидает ответ от сетевого узла.
            ds.setSoTimeout(2000);
            // Конфигурируем сокет на соответствующий адрес и порт
            ds.connect(ia, 137);
            // Создаем UDP пакет для отправки
            dpqry = new DatagramPacket(bqry, bqry.length);
            // Содаем UDP пакет для приема
            dprsp = new DatagramPacket(brsp, brsp.length);
            // Отправляем запрос
            ds.send(dpqry);
            // Получаем ответ
            ds.receive(dprsp);
            // Закрываем соединение
            ds.disconnect();
            ds.close();
            int error = dprsp.getData()[3] & 0x0f;
            if (error != 0) return "";
            int k = 0;
            if (can_read(72, 73)){
                NetBIOSNameCp866 = new byte[20];
                for (int i = 57; i < 72; i++){
                    NetBIOSNameCp866[k] = dprsp.getData()[i];
                    k++;
                    }
                }
            if ((can_read(90, 91))&&(NetBIOSNameCp866 == null)){
                NetBIOSNameCp866 = new byte[20];
                for (int i = 75; i < 90; i++){
                    NetBIOSNameCp866[k] = dprsp.getData()[i];
                    k++;
                    }
                }
            if ((can_read(108, 109))&&(NetBIOSNameCp866 == null)){
                NetBIOSNameCp866 = new byte[20];
                for (int i = 93; i < 108; i++){
                    NetBIOSNameCp866[k] = dprsp.getData()[i];
                    k++;
                    }
                }
            if ((can_read(126, 127))&&(NetBIOSNameCp866 == null)){
                NetBIOSNameCp866 = new byte[20];
                for (int i = 111; i < 126; i++){
                    NetBIOSNameCp866[k] = dprsp.getData()[i];
                    k++;
                    }
                }
            if ((can_read(144, 145))&&(NetBIOSNameCp866 == null)){
                NetBIOSNameCp866 = new byte[20];
                for (int i = 129; i < 144; i++){
                    NetBIOSNameCp866[k] = dprsp.getData()[i];
                    k++;
                    }
                }
            if (NetBIOSNameCp866 == null) return "";
            String NetBIOSName = new String(NetBIOSNameCp866, "Cp866");
            NetBIOSName = NetBIOSName.trim();
            if (correct_nbname(NetBIOSName) == true) return NetBIOSName;
            else return "";
            }
        catch (IOException ioe){
            ds.close();
            System.out.println("IOException " + this.hninfo.getIP() + ": " + ioe.toString());
            return "";
            }
        }
       
    }
Пояснения:
HostNetInfo - вспомогательный класс геттеров-сеттеров, который содержит поля МАС адрес, IP адрес, NetBIOS имя и DNS имя, все параметры строковые.

Проблема:
На основании этого класса опрашивается подсеть в 8К возможных адресов.
Работает хорошо, но заметил что в процессе опроса некоторые узлы возвращают только DNS имя, а NetBIOS имя остается пустым ("").
При этом тут же выполняю на эти узлы
ping -a XXX.XXX.XXX.XXX
и
nbtstat -A XXX.XXX.XXX.XXX
и нормально получаю оба имени - и DNS и NetBIOS.
Начал разбираться - запустил Wireshark, настроил фильтрацию на UDP и 137 порт, запускаю опрос на два IP адреса - один который нормально опрашивается (отдает оба имени) и второй - который отдает только DNS имя в результате опроса потоком. И вижу что с обоих адресов нормально приходят UDP пакеты с NetBIOS именем сетевых узлов.
При этом проблемный узел выдает эксепшн:
Java
1
System.out.println("IOException " + this.hninfo.getIP() + ": " + ioe.toString());
Дальнейшие разбирательства привели к следующему - эксепшн выкидывает строчка
Java
1
ds.receive(dprsp);
если установлен:
Java
1
ds.setSoTimeout(2000);
Если setSoTimeout не выставлять, то на проблемном узле поток живет бесконечно долго. У Фостера кстати этого параметра тоже нет.

Запускаю все это на Win7 Pro из NetBeans IDE 7.1.1 (Build 201203012225). Такое чувство, что Java просто не видит входящий UDP пакет, или не успевает его увидеть.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
26.04.2013, 05:55
Ответы с готовыми решениями:

DatagramSocket
Является ли udp socket открытый классом DatagramSocket асинхронным? т.е могут ли в одно и тоже...

Изменяем входящий пакет(изменяем Response) возможно?
Можно ли как-то изменить Response? Т.е. у меня есть текст на которые его изменить,но как это...

Почему если отправить пакет UDP и конечного адресата в сети не существует, то пакет не отправляется?
Добрый день! Вопрос для расширения кругозора. Мониторю свой трафик с помощью WireShark и...

Как определить, какой из подсетей принадлежит пакет IP-пакет?
То есть у Олиферов это всё подробно расписано. Если маршрутизация сделана на основе масок, то надо...

0
26.04.2013, 05:55
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
26.04.2013, 05:55
Помогаю со студенческими работами здесь

Квадраты при передаче через DatagramSocket
При передаче данных через DatagramPacket через DatagramSocket сообщение портится и выводятся...

UdpClient и Receive
Добрый день. Для прослушивание порта сделал отдельный поток и в нём реализовал обработку...

Receive прием пакетов
День добрый! Подскажите как получить весь ответ от запроса к сайту, с помощью Receive. Пробовал...

NetBIOS ф-ии Send и Receive
При операциях с NetBios есть две функции SEND (которая отправляет) и RECEIVE (которая принимает) по...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
1
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru