Форум программистов, компьютерный форум, киберфорум
C++: Сети
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.80/5: Рейтинг темы: голосов - 5, средняя оценка - 4.80
0 / 0 / 0
Регистрация: 02.02.2017
Сообщений: 29

Сырые (RAW) сокеты под виндой

15.07.2020, 09:45. Показов 1240. Ответов 13

Студворк — интернет-сервис помощи студентам
Всем доброго времени суток, пытаюсь завести сырые сокеты под виндой, написал простенькую программу которая по петле (127.0.0.1) шлет и принимает текстовую строку. Ошибок ни каких программа не выдает, и сообщение вроде как отсылается, только куда отсылается не понятно, wireshark тоже не видит пакет. Данный код без проблем работает под linux с поправками на систему. В чем может быть проблема?. Во вложении положу полный проект.
Код:
fmMain.h
C++
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
#ifndef FMMAIN_H
#define FMMAIN_H
 
#include <QWidget>
#include "Libs.h"
#include "sockWrapper.h"
 
QT_BEGIN_NAMESPACE
namespace Ui { class fmMain; }
QT_END_NAMESPACE
 
class fmMain : public QWidget
{
    Q_OBJECT
 
private:
    Ui::fmMain *ui;
    sockWrapper *conn;
 
public:
    fmMain(QWidget *parent = nullptr);
    ~fmMain();
 
private:
    void objOptions();
    void printNewMessage(QByteArray data);
 
private slots:
    void on_pushButton_connect_clicked();
    void on_pushButton_unConnect_clicked();
    void on_pushButton_listen_clicked();
    void on_pushButton_unListen_clicked();
    void on_pushButton_sendMessage_clicked();
 
 
 
};
#endif // FMMAIN_H
fmMain.cpp
C++
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
#include "fmMain.h"
#include "ui_fmMain.h"
 
fmMain::fmMain(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::fmMain)
{
    ui->setupUi(this);
    objOptions();
}
 
fmMain::~fmMain()
{
    delete ui;
}
 
void fmMain::objOptions()
{
    ui->lineEdit_sendIP->setText("127.0.0.1");
    ui->lineEdit_listenIP->setText("127.0.0.1");
    ui->lineEdit_sendPort->setText("2019");
    ui->lineEdit_listenPort->setText("2019");
    conn = new sockWrapper;
    conn->saveChannelOpt(QHostAddress(ui->lineEdit_sendIP->text()),QHostAddress(ui->lineEdit_listenIP->text()),ui->lineEdit_sendPort->text().toUInt(),ui->lineEdit_listenPort->text().toUInt());
    QObject::connect(conn, &sockWrapper::newMessage, this, &fmMain::printNewMessage);
}
 
void fmMain::printNewMessage(QByteArray data)
{
    ui->plainTextEdit_reciveMessage->appendPlainText(QString::fromStdString(data.toStdString()));
}
 
 
void fmMain::on_pushButton_connect_clicked()
{
    conn->connectTo();
}
 
void fmMain::on_pushButton_unConnect_clicked()
{
    conn->unconnectTo();
}
 
void fmMain::on_pushButton_listen_clicked()
{
    conn->listenTo();
}
 
void fmMain::on_pushButton_unListen_clicked()
{
    conn->unlistenTo();
}
 
void fmMain::on_pushButton_sendMessage_clicked()
{
    QByteArray msgData;
    msgData.append(ui->lineEdit_message->text());
    conn->sendTo(msgData);
}
sockWrapper.h
C++
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
#ifndef SOCKWRAPPER_H
#define SOCKWRAPPER_H
 
#include <QObject>
#include "Libs.h"
 
class sockWrapper : public QObject
{
    Q_OBJECT
 
private:
    struct iphdr
    {
        uint ihl : 4;
        uint version : 4;
        quint8 tos;
        quint16 tot_len;
        quint16 id;
        quint16 frag_off;
        quint8 ttl;
        quint8 protocol;
        quint16 check;
        quint32 saddr;
        quint32 daddr;
    };
    struct udphdr
    {
        quint16 source;
        quint16 dest;
        quint16 len;
        quint16 check;
    };
 
private:
    WSAData wData;
    SOCKET sockSend;
    SOCKET sockListen;
    sockaddr_in forSend;
    sockaddr_in forListen;
    QSocketNotifier *sockNotif;
    iphdr ip;
    udphdr udp;
 
public:
    explicit sockWrapper(QObject *parent = nullptr);
    ~sockWrapper();
    void saveChannelOpt(QHostAddress sendAddr, QHostAddress listenAddr, quint16 sendPort, quint16 listenPort);
    void connectTo();
    void unconnectTo();
    void listenTo();
    void unlistenTo();
    void sendTo(QByteArray data);
 
private:
    void WSAStart();
    void WSAClean();
    void reciveNewMessage();
 
signals:
    void newMessage(QByteArray data);
 
};
 
#endif // SOCKWRAPPER_H
sockWrapper.cpp
C++
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
#include "sockWrapper.h"
 
static unsigned long crc32 ( char *buff, unsigned long len)
{
    unsigned long crc_table[256];
    unsigned long crc;
    for (int i = 0; i < 256; ++i)
    {
        crc = i;
        for (int j = 0; j < 8; ++j)
        {
            crc = crc & 1 ? (crc >> 1) ^ 0xEDB88320UL : crc >> 1;
        }
        crc_table[i] = crc;
    }
    crc = 0xFFFFFFFFUL;
    while (--len)
    {
        crc = crc_table[(crc ^ *buff++) & 0xFF] ^ (crc >> 8);
    }
    return crc ^ 0xFFFFFFFFUL;
}
 
sockWrapper::sockWrapper(QObject *parent) : QObject(parent)
{
    WSAStart();
}
 
sockWrapper::~sockWrapper()
{
    WSAClean();
}
 
void sockWrapper::saveChannelOpt(QHostAddress sendAddr, QHostAddress listenAddr, quint16 sendPort, quint16 listenPort)
{
    forSend.sin_family = AF_INET;
    forSend.sin_addr.s_addr = htonl(sendAddr.toIPv4Address());
    forSend.sin_port = htons(sendPort);
    forListen.sin_family = AF_INET;
    forListen.sin_addr.s_addr = htonl(listenAddr.toIPv4Address());
    forListen.sin_port = htons(listenPort);
}
 
void sockWrapper::connectTo()
{
    shutdown(sockSend,2);
    sockSend = socket(PF_INET, SOCK_RAW, IPPROTO_UDP);
    if (sockSend < 0)
    {
        perror("socket");
        return;
    }
    else
    {
        if (::connect(sockSend,(struct sockaddr*) &forSend, sizeof(forSend)) < 0)
        {
            perror("connect");
        }
        else
        {
            return;
        }
    }
}
 
void sockWrapper::unconnectTo()
{
    shutdown(sockSend,2);
}
 
void sockWrapper::listenTo()
{
    shutdown(sockListen,2);
    sockListen = socket(PF_INET, SOCK_RAW, IPPROTO_UDP);
    if (sockListen < 0)
    {
        perror("socket");
        return;
    }
    else
    {
        if (::bind(sockListen,(struct sockaddr*) &forListen, sizeof(forListen)) < 0)
        {
            perror("bind");
            return;
        }
        else
        {
            sockNotif = new QSocketNotifier(sockListen,QSocketNotifier::Read,this);
            QObject::connect(sockNotif, &QSocketNotifier::activated, this, &sockWrapper::reciveNewMessage);
            return;
        }
    }
}
 
void sockWrapper::unlistenTo()
{
    shutdown(sockListen,2);
    QObject::disconnect(sockNotif, &QSocketNotifier::activated, this, &sockWrapper::reciveNewMessage);
}
 
void sockWrapper::sendTo(QByteArray data)
{
    ip.version = 4;
    ip.frag_off = 0;
    ip.ttl = 64;
    ip.protocol = IPPROTO_UDP;
    ip.saddr = forListen.sin_addr.s_addr;
    ip.daddr = forSend.sin_addr.s_addr;
    ip.tos = 10;
    ip.tot_len = sizeof(iphdr) + sizeof(udphdr) + data.size();
    ip.ihl = 5;
    ip.check = crc32(data.data(),data.size());
    udp.len = htons(sizeof(udphdr) + data.size());
    udp.dest = forSend.sin_port;
    udp.source = forListen.sin_port;
    udp.check = 1;
    char Packet[ip.tot_len];
    uint lastPos = 0;
    for (uint i = 0; i < sizeof(ip); ++i)
    {
        Packet[lastPos] = (*((char*)(&ip)+i));
        ++lastPos;
    }
    for (uint i = 0; i < sizeof(udp); ++i)
    {
        Packet[lastPos] = (*((char*)(&udp)+i));
        ++lastPos;
    }
    for (uint i = 0; i < data.size(); ++i)
    {
        Packet[lastPos] = data.at(i);
        ++lastPos;
    }
    int one = 1;
    const int *val = &one;
    if (::setsockopt(sockSend,IPPROTO_IP,IP_HDRINCL,(char*)val,sizeof(one)) < 0)
    {
        perror("setsockopt");
    }
    else
    {
        if (::sendto(sockSend, Packet, ip.tot_len, 0, (struct sockaddr *) &forSend, sizeof(forSend)) < 0)
        {
            perror("sendto");
            return;
        }
    }
    QByteArray test;
    test.append("Message send");
    emit newMessage(test);
 
}
 
void sockWrapper::WSAStart()
{
 
    if (WSAStartup(MAKEWORD(2, 2), &wData) == 0)
    {
        QMessageBox::information(NULL,"WSA","WSA success");
    }
}
 
void sockWrapper::WSAClean()
{
    WSACleanup();
}
 
void sockWrapper::reciveNewMessage()
{
    char dataBuffer[4096];
    ssize_t bytesNumber = 0;
    QByteArray result;
    int size = sizeof(forListen);
    if ((bytesNumber = ::recvfrom(sockListen, dataBuffer ,4096 ,0 ,(sockaddr*)&forListen, &size)) < 0)
    {
        perror("recv");
        return;
    }
    else
    {
        result.append(dataBuffer,bytesNumber);
        emit newMessage(result);
    }
}
Libs.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#ifndef LIBS_H
#define LIBS_H
 
///Для сокетов
#include <winsock2.h>
#include <ws2tcpip.h> // для IP_HDRINCL
#include <QSocketNotifier>
#include <QHostAddress>
///Общее
#include <QByteArray>
#include <QMessageBox>
#include <QDebug>
 
 
#endif // LIBS_H
.pro -файл
C++
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
QT       += core gui network
 
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
 
CONFIG += c++11
 
DEFINES += QT_DEPRECATED_WARNINGS
 
SOURCES += \
    main.cpp \
    fmMain.cpp \
    sockWrapper.cpp
 
HEADERS += \
    Libs.h \
    fmMain.h \
    sockWrapper.h
 
FORMS += \
    fmMain.ui
 
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
 
LIBS += -lws2_32
Вложения
Тип файла: 7z SockRawTest.7z (3.4 Кб, 0 просмотров)
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
15.07.2020, 09:45
Ответы с готовыми решениями:

Сырые сокеты
Всем доброго времени суток. {Target} -------- (Internet) ------ {Prov} -------- ip:91.1.2.3.4 ip:91.1.5.6 ...

Сырые сокеты ----> ПЭМИН, возможно?
Здравствуйте, дорогие участники форума. Я хотел бы попросить Вас об одной просьбе. Голову ломаю над решением одной задачи. В двух словах -...

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

13
848 / 651 / 323
Регистрация: 24.02.2017
Сообщений: 2,297
15.07.2020, 10:05
https://docs.microsoft.com/ru-... dfrom=MSDN
0
0 / 0 / 0
Регистрация: 02.02.2017
Сообщений: 29
15.07.2020, 11:02  [ТС]
Я это читал и вроде как все соответствует, все заголовки написаны правильно и функции используются тоже правильно.
0
Неэпический
 Аватар для Croessmah
18149 / 10731 / 2067
Регистрация: 27.09.2012
Сообщений: 27,035
Записей в блоге: 1
15.07.2020, 11:28
Сокеты под виндой и под линуксами имеют различия, так что просто взять и перенести одно в другое не получится.
К примеру,
Цитата Сообщение от DarkMadar Посмотреть сообщение
sockSend = socket(PF_INET, SOCK_RAW, IPPROTO_UDP);
    if (sockSend < 0)
Под виндой тип SOCKET - беззнаковый, так что такое сравнение смысла не имеет.
Функция socket возвращает INVALID_SOCKET (~0) в случае неудачи.

Цитата Сообщение от DarkMadar Посмотреть сообщение
perror("sendto");
Для ошибок нужно использовать GetLastError (WSAGetLastError) и FormatMessage.

Также учтите, что сырые сокеты очень хорошо глушатся антивирусными файрволами.
1
0 / 0 / 0
Регистрация: 02.02.2017
Сообщений: 29
15.07.2020, 12:23  [ТС]
Про perror("") я знал, просто не стал менять так как ни одна точка останова не сработала в этих ветках условия, а вот про то что под виндой сокеты беззнаковые, нет, за это спасибо. И я так понимаю отследить сам факт того что мои сокеты глушатся нельзя? Я уже читал про это и вырубил все что можно на компе, это фаервол и дефендер винды, антивирусы я ни какие не ставил.
0
Неэпический
 Аватар для Croessmah
18149 / 10731 / 2067
Регистрация: 27.09.2012
Сообщений: 27,035
Записей в блоге: 1
15.07.2020, 12:37
Цитата Сообщение от DarkMadar Посмотреть сообщение
И я так понимаю отследить сам факт того что мои сокеты глушатся нельзя?
Не могу сказать, но когда мой сниффер глушился файрволом, просто переставали перехватываться пакеты. Никаких ошибок при этом не возникало.

Я не разбирался с вашим кодом, но вот это смущает:
C++
1
ip.check = crc32(data.data(),data.size());
В ip-заголовке должна быть контрольная сумма заголовка, а не данных пакета. Плюс ко всему для нее отводится 16 бит и это не crc32.
1
0 / 0 / 0
Регистрация: 02.02.2017
Сообщений: 29
15.07.2020, 13:00  [ТС]
У меня на поле check отведено именно 16 бит, а crc32 это один из многих методов получения контрольной суммы, а если туда положить контрольную сумму заголовка разве она не будет всегда одинаковой? Заголовок же всегда 20 байт, смысла же в этом поле не будет тогда. Значит вероятнее всего что то глушит мою программу, буду копать в этом направлении тогда. Спасибо за помощь.
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,818
15.07.2020, 13:04
Цитата Сообщение от DarkMadar Посмотреть сообщение
меня на поле check отведено именно 16 бит, а crc32 это один из многих методов получения контрольной суммы
Тогда должно быть Сrc16 (не говоря уже про то, что полином для расчета должен быть вполне определенный, а не произвольный).
Сrc32 считает 32-битную контрольную сумму, которую вы обрезаете до 16 разрядов при присваивании.
Даже в отрыве от задачи сетевого взаимодействия это совершенно некорректно.
1
0 / 0 / 0
Регистрация: 02.02.2017
Сообщений: 29
15.07.2020, 13:06  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
Тогда должно быть Сrc16 (не говоря уже про то, что полином для расчета должен быть вполне определенный, а не произвольный).
Сrc32 считает 32-битную контрольную сумму, которую вы обрезаете до 16 разрядов при присваивании.
Даже в отрыве от задачи сетевого взаимодействия это совершенно некорректно.
Спасибо за замечание, я учту
0
Неэпический
 Аватар для Croessmah
18149 / 10731 / 2067
Регистрация: 27.09.2012
Сообщений: 27,035
Записей в блоге: 1
15.07.2020, 13:07
Цитата Сообщение от DarkMadar Посмотреть сообщение
а crc32 это один из многих методов получения контрольной суммы
crc32 - это 32-ух битная сумма.
Для заголовка IP сумма вычисляется согласно этому: https://www.ietf.org/rfc/rfc1071.txt
Цитата Сообщение от DarkMadar Посмотреть сообщение
Заголовок же всегда 20 байт, смысла же в этом поле не будет тогда
Это у вас так, но это не обязательно. Заголовок IP может быть больше 20 байт.
К тому же, данные в нем меняются и, следовательно, меняется и контрольная сумма.

Цитата Сообщение от DarkMadar Посмотреть сообщение
Значит вероятнее всего что то глушит мою программу, буду копать в этом направлении тогда.
Возможно, из-за ошибок в заголовке, пакет считается "битым" и никуда не уходит. Но это не точно.
1
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,818
15.07.2020, 13:08
DarkMadar, https://tools.ietf.org/html/rfc1071

Добавлено через 41 секунду
Croessmah, оп, ты уже дал ссылку на RFC ну тогда моя лишняя.
1
0 / 0 / 0
Регистрация: 02.02.2017
Сообщений: 29
15.07.2020, 13:13  [ТС]
Спасибо за ссылку. Под linux пакеты без проблем отправляются.
0
Неэпический
 Аватар для Croessmah
18149 / 10731 / 2067
Регистрация: 27.09.2012
Сообщений: 27,035
Записей в блоге: 1
15.07.2020, 13:25
Цитата Сообщение от DarkMadar Посмотреть сообщение
Под linux пакеты без проблем отправляются.
Под линуксом, кстати, имеется функция ip_fast_csum.
C++
1
ip.check = ip_fast_csum(&ip, ip.ihl);
Добавлено через 2 минуты
How to Calculate IP Header Checksum (With an Example)
1
0 / 0 / 0
Регистрация: 02.02.2017
Сообщений: 29
15.07.2020, 13:28  [ТС]
Да под линуксом и структуры для заголовков есть. А за функцию спасибо, не знал о ней.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
15.07.2020, 13:28
Помогаю со студенческими работами здесь

RAW сокеты
как использовать RAW сокеты ? я знаю что это возможно при помощи старого драивера (пегед тем как его заменили &quot;hotfix&quot;-oм) но...

Сырые сокеты
Не нашёл хорошего описания и примеров использования сырых сокетов. Можете покидать ссылочки? :3

Блокировка пакетов. Сырые сокеты
Задача стоит в блокировании некоторых веб-сайтов, например Вконтакте или одноклассники. Делаю через сырые сокеты SocketType.Raw. Получился...

RAW сокеты в Java
Необходимо отправить пакет по локальной сети без создания сервера без открытия портов без привязки к IP. В СИ пакет просто...

Raw сокеты и icmp
Привет! Помогите, пожалуйста. Есть raw сокет, который должен перехватывать все входящие icmp сообщения icmpSocket = new...


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

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Новые блоги и статьи
Программный контроль заполнения реквизита табличной части документа
Maks 03.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: реализовать контроль заполнения реквизита "ПричинаСписания". . .
wmic не является внутренней или внешней командой
Maks 02.04.2026
Решение: DISM / Online / Add-Capability / CapabilityName:WMIC~~~~ Отсюда: https:/ / winitpro. ru/ index. php/ 2025/ 02/ 14/ komanda-wmic-ne-naydena/
Программная установка даты и запрет ее изменения
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: при создании документов установить период списания автоматически. . .
Вывод данных в справочнике через динамический список
Maks 01.04.2026
Реализация из решения ниже выполнена на примере нетипового справочника "Спецтехника" разработанного в конфигурации КА2. Задача: вывести данные из ТЧ нетипового документа. . .
Программное заполнения текстового поля в реквизите формы документа
Maks 01.04.2026
Алгоритм из решения ниже реализован на нетиповом документе "ВыдачаОборудованияНаСпецтехнику" разработанного в конфигурации КА2, в дополнении к предыдущему решению. На форме документа создается. . .
К слову об оптимизации
kumehtar 01.04.2026
Вспоминаю начало 2000-х, университет, когда я писал на Delphi. Тогда среди программистов на форумах активно обсуждали аккуратную работу с памятью: нужно было следить за переменными, вовремя. . .
Идея фильтра интернета (сервер = слой+фильтр).
Hrethgir 01.04.2026
Суть идеи заключается в том, чтобы запустить свой сервер, о чём я если честно мечтал давно и давно приобрёл книгу как это сделать. Но не было причин его запускать. Очумелые учёные напечатали на. . .
Модель здравосоХранения 6. ESG-повестка и устойчивое развитие; углублённый анализ кадрового бренда
anaschu 31.03.2026
В прикрепленном документе раздумья о том, как можно поменять модель в будущем
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru