Аватар для Yandex
3 / 3 / 1
Регистрация: 31.01.2013
Сообщений: 63

Простой клиент-сервер с использованием сырых сокетов

01.02.2016, 18:28. Показов 4110. Ответов 2

Студворк — интернет-сервис помощи студентам
Здравствуйте!
Уже целую неделю бьюсь над вопросом "Как создать простой клиент-сервер с использованием сырых сокетов (raw sockets)?" .
Я разбирал структуру разных пакетов для передачи данных (TCP, IP, UDP), но ничего не получается; к этому сообщению прилагаю код структур которые я написал:
Пакет IP:
Кликните здесь для просмотра всего текста

C++
1
2
3
4
5
6
7
8
9
10
11
12
typedef struct IPHeader {
  UCHAR   iph_verlen;   // версия и длина заголовка
  UCHAR   iph_tos;      // тип сервиса
  USHORT  iph_length;   // длина всего пакета
  USHORT  iph_id;       // Идентификация
  USHORT  iph_offset;   // флаги и смещения
  UCHAR   iph_ttl;      // время жизни пакета
  UCHAR   iph_protocol; // протокол
  USHORT  iph_xsum;     // контрольная сумма
  ULONG   iph_src;      // IP-адрес отправителя
  ULONG   iph_dest;     // IP-адрес назначения
} IPHeader;


Пакет TCP (это нашел в интернете):
Кликните здесь для просмотра всего текста

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
struct tcp_header 
{
    unsigned short source_port;
    unsigned short dest_port;
    unsigned int   sequence_number;
    unsigned int   ack_number;
    unsigned char data_offset;
    #define TH_OFF(th)  (((th)->data_offset & 0xf0) >> 4)
    unsigned char   flags;
    #define TH_FIN  0x01
    #define TH_SYN  0x02
    #define TH_RST  0x04
    #define TH_PUSH 0x08
    #define TH_ACK  0x10
    #define TH_URG  0x20
    #define TH_ECNECHO  0x40   
    #define TH_CWR      0x80 
    unsigned short window_size;
    unsigned short checksum;
    unsigned short urgpointer;
};


Пакет UDP:
Кликните здесь для просмотра всего текста

C++
1
2
3
4
5
6
typedef struct UDPHeader {
  USHORT udph_xsum;
  USHORT udph_length;
  USHORT udph_src;
  USHORT udph_dest;
} UDPHeader;


Средой разработки которой я пользуюсь Visual Studio 2008 C++ на ОС Windows XP.
Надеюсь, что кто то встречал данную проблему и поможет мне.

Добавлено через 4 часа 56 минут
Вот попытался создать клиент-сервер (UDP) клиент не может подключится к серверу(
Пример кода
Сервер:
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
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
 
#pragma comment ( lib, "ws2_32.lib" )
 
int __cdecl main(void) 
{
    WSADATA wsaData;
    SOCKET SendRecvSocket;  // сокет для приема и передачи
    sockaddr_in ServerAddr, ClientAddr;  // это будет адрес сервера и клиентов
    int err, maxlen = 512, ClientAddrSize=sizeof(ClientAddr);  // код ошибки, размер буферов и размер структуры адреса
    char* recvbuf=new char[maxlen];  // буфер приема
    char* result_string=new char[maxlen];  // буфер отправки
 
 
    // Initialize Winsock
    WSAStartup(MAKEWORD(2,2), &wsaData);
 
    // Create a SOCKET for connecting to server
    SendRecvSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
 
    // Setup the TCP listening socket
    ServerAddr.sin_family=AF_INET;
    ServerAddr.sin_addr.s_addr=inet_addr("127.0.0.1");
    ServerAddr.sin_port=htons(1723);
    err = bind( SendRecvSocket, (sockaddr *) &ServerAddr, sizeof(ServerAddr));
    if (err == SOCKET_ERROR) {
        printf("bind failed: %d\n", WSAGetLastError());
        closesocket(SendRecvSocket);
        WSACleanup();
        return 1;
    }
 
    while (true) {
        // Accept a client socket
        err = recvfrom(SendRecvSocket,recvbuf,maxlen,0,(sockaddr *)&ClientAddr,&ClientAddrSize);
        if (err > 0) {
            recvbuf[err]=0;
            printf("Received query: %s\n", (char* )recvbuf);
            // вычисляем результат
            int result=72;
            _snprintf_s(result_string,maxlen,maxlen,"OK %d\n",result);
            // отправляем результат на сервер
            sendto(SendRecvSocket,result_string,strlen(result_string),0,(sockaddr *)&ClientAddr,sizeof(ClientAddr));
            printf("Sent answer: %s\n", result_string);
        }
        else  {
            printf("recv failed: %d\n", WSAGetLastError());
            closesocket(SendRecvSocket);
            WSACleanup();
            return 1;
        }
    }
}
Клиент:
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
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
 
// В опциях проекта, в разделе Linker, в пункте Additional Dependancies укажите Ws2_32.lib
 #pragma comment ( lib, "ws2_32.lib" )
 
typedef struct IPHeader {
    UCHAR   iph_verlen;
    UCHAR   iph_ver;
    UCHAR   iph_tos;
    USHORT  iph_length;
    USHORT  iph_id;
    USHORT  iph_offset;
    UCHAR   iph_ttl;
    UCHAR   iph_protocol;
    USHORT  iph_xsum;
    UINT    iph_src;
    UINT    iph_dest;
} IPHeader;
 
typedef struct UDPHeader {
    USHORT  udph_xsum;
    USHORT  udph_length;
    USHORT  udph_src;
    USHORT  udph_dest;
} UDPHeader;
 
#define pack_size sizeof(struct IPHeader) + sizeof(struct UDPHeader)
 
int __cdecl main(void) 
{
    WSADATA wsaData;
    SOCKET SendRecvSocket;  // сокет для приема и передачи
    sockaddr_in ServerAddr;  // это будет адрес сервера и клиентов
    int err, maxlen = 512;  // код ошибки, размер буферов и размер структуры адреса
    char* recvbuf=new char[maxlen];  // буфер приема
    char* query=new char[maxlen];  // буфер отправки
 
 
    // Initialize Winsock
    WSAStartup(MAKEWORD(2,2), &wsaData);
 
    // Create a SOCKET for connecting to server
    SendRecvSocket = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
 
    char data[40] = {'y','e','s'};
    unsigned short PacketS = sizeof(IPHeader) + sizeof(UDPHeader) + sizeof(data);
    char* inner_packet = (char *) malloc(PacketS); if (inner_packet == NULL) return -1;
    memset(inner_packet, 0, PacketS);
    
    IPHeader *ip_head = (struct IPHeader*) inner_packet;
    ip_head->iph_verlen = 0x04;
    ip_head->iph_ver = 0x05;
    ip_head->iph_protocol = IPPROTO_UDP;
    ip_head->iph_length = pack_size + 7;
    ip_head->iph_id = htons(0x0001);
    ip_head->iph_offset = htons(0x4000);;
    ip_head->iph_ttl = 128;
    ip_head->iph_xsum = 0;
    ip_head->iph_tos = 0;
    ip_head->iph_src = INADDR_ANY;
    ip_head->iph_dest = INADDR_ANY;
 
    UDPHeader *udp_head = (struct UDPHeader*)(inner_packet + sizeof(struct IPHeader));
    udp_head->udph_xsum = 0;
    udp_head->udph_src = htons(1723);
    udp_head->udph_dest = htons(5433);
    udp_head->udph_length = htons(sizeof(UDPHeader) + sizeof(data));
    
    for(int t = 0; t < sizeof(data); t++) inner_packet[t + sizeof(IPHeader) + sizeof(UDPHeader)] = data[t];
    
    ServerAddr.sin_family = AF_INET;
    ServerAddr.sin_addr.s_addr = * (DWORD *) (inner_packet + 16);
    ServerAddr.sin_port=htons(1723);
 
    _snprintf_s(query,maxlen,maxlen,"CALC * 12 6\n");
    // отправляем запрос на сервер
    sendto(SendRecvSocket, inner_packet, PacketS, 0, (sockaddr *)&ServerAddr,sizeof(ServerAddr));  
    printf("Sent: %s\n", query);
 
    // получаем результат
    err = recvfrom(SendRecvSocket,recvbuf,maxlen,0,0,0);
    if (err > 0) {
        recvbuf[err]=0;
        printf("Result: %s\n", (char* )recvbuf);
    }
    else {
        printf("recv failed: %d\n", WSAGetLastError());
        closesocket(SendRecvSocket);
        WSACleanup();
        return 1;
    }
 
    closesocket(SendRecvSocket);
 
}
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
01.02.2016, 18:28
Ответы с готовыми решениями:

Приложения клиент, сервер с использованием сокетов
Запускаю одновременно оба приложения. В клиентское ввожу &quot;localhost&quot;, нажимаю &quot;установить соединение&quot;. Сокет в серверном создаётся...

Создание сырых сокетов
Есть программа которая создает сырые сокеты, для этого ее нужно запускать от супер пользователя. Можно это как нибудь обойти? Указать...

Приём сырых сокетов
Отправляю сырой сокет следующим кодом, но принять никак не могу. ОС: ubuntu //Create a raw socket int s = socket...

2
 Аватар для Yandex
3 / 3 / 1
Регистрация: 31.01.2013
Сообщений: 63
02.02.2016, 21:55  [ТС]
Наконец то получил клиент-сервер на основе сырых сокетов. Возникла проблема как считывать значение IP и UDP пакета, что бы выводилось на сервере (например конкретное значение адреса клиента, порта клиента, флагов).
Клиент:
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
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
#include <pshpack1.h>
#include <wspiapi.h>
#pragma comment ( lib, "ws2_32.lib" )
#include <iostream>
using namespace std;
typedef struct ip_hdr
{
 
    unsigned char  ip_verlen;        // 4-bit IPv4 version
                                     // 4-bit header length (in 32-bit words)
    unsigned char  ip_tos;           // IP type of service
    unsigned short ip_totallength;   // Total length
    unsigned short ip_id;            // Unique identifier
    unsigned short ip_offset;        // Fragment offset field
    unsigned char  ip_ttl;           // Time to live
    unsigned char  ip_protocol;      // Protocol(TCP,UDP etc)
    unsigned short ip_checksum;      // IP checksum
    unsigned int   ip_srcaddr;       // Source address
    unsigned int   ip_destaddr;      // Source address
} IPV4_HDR, *PIPV4_HDR, FAR * LPIPV4_HDR;
 
typedef struct udp_hdr
{
    unsigned short src_portno;       // Source port no.
    unsigned short dst_portno;       // Dest. port no.
    unsigned short udp_length;       // Udp packet length
    unsigned short udp_checksum;     // Udp checksum
} UDP_HDR, *PUDP_HDR;
 
USHORT checksum(USHORT *buffer, int size)
{
    unsigned long cksum = 0;
    while (size > 1)
    {
        cksum += *buffer++;
        size  -= sizeof(USHORT);  
    }
    if (size)
    {
        cksum += *(UCHAR*)buffer;  
        cksum = (cksum >> 16) + (cksum & 0xffff);
        cksum += (cksum >> 16);
    }
    return (USHORT)(~cksum);
}
 
UDP_HDR *udphdr;
IPV4_HDR *v4hdr;
struct addrinfo *ressrc, *resdest;
struct addrinfo hints;
WSADATA wsd;
SOCKET s;
char *buffer;
int optval = 1;
int _cdecl main(int argc, char **argv)
{
    WSAStartup(MAKEWORD(2,2), &wsd);
    getaddrinfo("1.2.3.4","4534",0,&ressrc );
    hints.ai_flags  = 0;
    hints.ai_family = ressrc->ai_family;
    hints.ai_socktype = ressrc->ai_socktype;
    hints.ai_protocol = ressrc->ai_protocol;
    getaddrinfo("127.0.0.1","5000",&hints,&resdest);
    s = socket(ressrc->ai_family, SOCK_RAW, ressrc->ai_protocol);
 
    if( setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *)&optval, sizeof(optval)) ){
        // Ошибка
        printf("Error setsockopt %d\n", WSAGetLastError());
        closesocket(s); // закрываем сокет!
        WSACleanup();
        return -1;
    }
    buffer = (char *)HeapAlloc(GetProcessHeap(), 0, 132);
    v4hdr = (IPV4_HDR *)buffer;
    v4hdr->ip_verlen = (4 << 4) | (sizeof(IPV4_HDR) / sizeof(unsigned long));
    v4hdr->ip_tos = 0;
    v4hdr->ip_totallength = htons(sizeof(IPV4_HDR)+ sizeof(UDP_HDR) + 15);
    v4hdr->ip_id = 0;
    v4hdr->ip_offset = 0;
    v4hdr->ip_ttl = (unsigned char)8;
    v4hdr->ip_protocol = (unsigned char)IPPROTO_UDP;
    v4hdr->ip_checksum = 56;
    v4hdr->ip_srcaddr = inet_addr("127.0.0.1");
    v4hdr->ip_destaddr = inet_addr("127.0.0.1");
    v4hdr->ip_checksum    = checksum((unsigned short *)v4hdr, sizeof(IPV4_HDR));
    udphdr = (UDP_HDR *)(buffer + sizeof(IPV4_HDR));
    udphdr->src_portno = ((struct sockaddr_in *)ressrc->ai_addr)->sin_port;
    udphdr->dst_portno = ((struct sockaddr_in *)resdest->ai_addr)->sin_port;
    udphdr->udp_length = htons(sizeof(UDP_HDR) + 15);
    memcpy(buffer + sizeof(IPV4_HDR) + sizeof(UDP_HDR),"Privet kak dela", 15);
 
    sendto(s, buffer, sizeof(IPV4_HDR) + sizeof(UDP_HDR) + 15 ,0,resdest->ai_addr, resdest->ai_addrlen);
    sendto(s, buffer, sizeof(IPV4_HDR) + sizeof(UDP_HDR) + 15 ,0,resdest->ai_addr, resdest->ai_addrlen);
}
Сервер:
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
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
#include <pshpack1.h>
#include <wspiapi.h>
#pragma comment ( lib, "ws2_32.lib" )
#include <iostream>
using namespace std;
typedef struct ip_hdr
{
 
    unsigned char  ip_verlen;        // 4-bit IPv4 version
                                     // 4-bit header length (in 32-bit words)
    unsigned char  ip_tos;           // IP type of service
    unsigned short ip_totallength;   // Total length
    unsigned short ip_id;            // Unique identifier
    unsigned short ip_offset;        // Fragment offset field
    unsigned char  ip_ttl;           // Time to live
    unsigned char  ip_protocol;      // Protocol(TCP,UDP etc)
    unsigned short ip_checksum;      // IP checksum
    unsigned int   ip_srcaddr;       // Source address
    unsigned int   ip_destaddr;      // Source address
} IPV4_HDR, *PIPV4_HDR, FAR * LPIPV4_HDR;
 
typedef struct udp_hdr
{
    unsigned short src_portno;       // Source port no.
    unsigned short dst_portno;       // Dest. port no.
    unsigned short udp_length;       // Udp packet length
    unsigned short udp_checksum;     // Udp checksum
} UDP_HDR, *PUDP_HDR;
 
USHORT checksum(USHORT *buffer, int size)
{
    unsigned long cksum = 0;
    while (size > 1)
    {
        cksum += *buffer++;
        size  -= sizeof(USHORT);  
    }
    if (size)
    {
        cksum += *(UCHAR*)buffer;  
        cksum = (cksum >> 16) + (cksum & 0xffff);
        cksum += (cksum >> 16);
    }
    return (USHORT)(~cksum);
}
 
UDP_HDR *udphdr;
IPV4_HDR *v4hdr;
struct addrinfo *ressrc, *resdest;
struct addrinfo hints;
WSADATA wsd;
SOCKET s;
char *buffer;
int optval = 1;
int _cdecl main(int argc, char **argv)
{
    WSAStartup(MAKEWORD(2,2), &wsd);
    getaddrinfo("1.2.3.4","4534",0,&ressrc );
    hints.ai_flags  = 0;
    hints.ai_family = ressrc->ai_family;
    hints.ai_socktype = ressrc->ai_socktype;
    hints.ai_protocol = ressrc->ai_protocol;
    getaddrinfo("127.0.0.1","5000",&hints,&resdest);
    s = socket(ressrc->ai_family, SOCK_RAW, ressrc->ai_protocol);
 
    if( setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *)&optval, sizeof(optval)) ){
        // Ошибка
        printf("Error setsockopt %d\n", WSAGetLastError());
        closesocket(s); // закрываем сокет!
        WSACleanup();
        return -1;
    }
    buffer = (char *)HeapAlloc(GetProcessHeap(), 0, 132);
    v4hdr = (IPV4_HDR *)buffer;
    v4hdr->ip_verlen = (4 << 4) | (sizeof(IPV4_HDR) / sizeof(unsigned long));
    v4hdr->ip_tos = 0;
    v4hdr->ip_totallength = htons(sizeof(IPV4_HDR)+ sizeof(UDP_HDR) + 15);
    v4hdr->ip_id = 0;
    v4hdr->ip_offset = 0;
    v4hdr->ip_ttl = (unsigned char)8;
    v4hdr->ip_protocol = (unsigned char)IPPROTO_UDP;
    v4hdr->ip_checksum = 56;
    v4hdr->ip_srcaddr = inet_addr("127.0.0.1");
    v4hdr->ip_destaddr = inet_addr("127.0.0.1");
    v4hdr->ip_checksum    = checksum((unsigned short *)v4hdr, sizeof(IPV4_HDR));
    udphdr = (UDP_HDR *)(buffer + sizeof(IPV4_HDR));
    udphdr->src_portno = ((struct sockaddr_in *)ressrc->ai_addr)->sin_port;
    udphdr->dst_portno = ((struct sockaddr_in *)resdest->ai_addr)->sin_port;
    udphdr->udp_length = htons(sizeof(UDP_HDR) + 15);
    memcpy(buffer + sizeof(IPV4_HDR) + sizeof(UDP_HDR),"Privet kak dela", 15);
 
    sendto(s, buffer, sizeof(IPV4_HDR) + sizeof(UDP_HDR) + 15 ,0,resdest->ai_addr, resdest->ai_addrlen);
    sendto(s, buffer, sizeof(IPV4_HDR) + sizeof(UDP_HDR) + 15 ,0,resdest->ai_addr, resdest->ai_addrlen);
}
Можно ли менять IP адрес отправителя?
2
0 / 0 / 0
Регистрация: 11.02.2017
Сообщений: 1
19.09.2018, 20:40
Ты записал один и тот же код в своем ответе. Что в клиент, что в сервер. Не мог бы ты поправить? Я просто разобраться хочу, а твой пример подойдет почти идеально

Добавлено через 27 минут
Только что я потыкался и понял, что сервер менять не нужно. Для того, чтобы клиент и сервер сконтачились достаточно поправить номер порта в коде сервера. Время редактирования предыдущего сообщения истекло, поэтому я написал это сообщение
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
19.09.2018, 20:40
Помогаю со студенческими работами здесь

Создать клиент, принимающий данные с использованием сокетов
Всем привет, пожалуйста подскажите как мне сделать КЛИЕНТ на c++, чтобы можно было передавать и получать данные(просто строки). Слово...

Написать сервер с использованием сокетов
Ребята, нужно написать сервер за неделю на си++ с использованием сокетов, а я в этом вообще не понимаю ничего. Помогите литературой...

Пишу клиент для HTTPS с использованием сокетов. При тесте получаю ответ 302 и непонятную строку location
Привет! Вообще пишу на яве, но вопрос явы не касается. Вопрос касается наверное больше веб программирования, но специального раздела не...

Простой клиент-сервер
Здравствуйте. Помогите реализовать простенький код с пояснениями. В клиенте при нажатии на кнопку делается скриншот экрана и отправляется...

Простой клиент-сервер
Добрый день/ вечер/ночь/ утро Смотрю простой пример клиент-сервера(а в этом деле я профан) import java.io.IOException; ...


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

Или воспользуйтесь поиском по форуму:
3
Ответ Создать тему
Опции темы

Новые блоги и статьи
Облачные приложения на Rust: руководство по архитектуре микросервисов
golander 13.07.2025
Когда я впервые взялся за проектирование облачной платформы для одного из наших клиентов, выбор стоял между привычными Go и Java. Но после нескольких месяцев разработки микросервисной системы,. . .
Как Node.js выполняет асинхронные операции
Reangularity 13.07.2025
Каждый раз, когда я рассказываю про Node. js, возникает один и тот же вопрос: "Как эта штука может быть быстрой, если JavaScript — однопоточный язык?" И это действительно кажется парадоксом. Ведь в. . .
Как писать чистый, тестируемый и качественный код на Python
py-thonny 12.07.2025
Помню свой первый проект на Python. Работал тогда быстро, грязно, лишь бы работало. Код был похож на запутанный клубок - переменные по одной букве, функции на 200 строк, комментарии отсутствовали как. . .
Blazor и контроллер сервопривода IoT Meadow Maple
Wired 11.07.2025
Я решил разобраться, как можно соединить современные веб-технологии с миром "железа". Интересная комбинация получилась из Blazor в качестве веб-интерфейса и микроконтроллера Meadow с его веб-сервером. . .
Генерация OpenQASM из кода Q#
EggHead 10.07.2025
Летом 2024-го я начал эксперименты с библиотекой Q# Bridge, и знаете что? Она оказалась просто находкой для тех, кто работает на стыке разных квантовых экосистем. Основная фишка этой библиотеки -. . .
Изучаем новый шаблон ИИ-чата .NET AI Chat Web App
stackOverflow 10.07.2025
В . NET появилось интересное обновление - новый шаблон ИИ-чата под названием . NET AI Chat Web App. Когда я впервые наткнулся на анонс этого шаблона, то сразу понял, что Microsoft наконец-то. . .
Результаты исследования от команды ARP (июль 2025 г.)
Programma_Boinc 10.07.2025
Результаты исследования от команды ARP (июль 2025 г. ) Африканский проект по дождям (ARP) World Community Grid снова запущен! Мы рады поделиться обновленной информацией о нашем прогрессе с осени. . .
Angular vs Svelte - что лучше?
Reangularity 09.07.2025
Сегодня рынок разделился на несколько четких категорий: тяжеловесы корпоративного уровня (Angular), гибкие универсалы (React), прогрессивные решения (Vue) и новая волна компилируемых фреймворков. . .
Code First и Database First в Entity Framework
UnmanagedCoder 09.07.2025
Entity Framework дает нам свободу выбора, предлагая как Code First, так и Database First подходы. Но эта свобода порождает вечный вопрос — какой подход выбрать? Entity Framework — это. . .
Как использовать Bluetooth-модуль HC-05 с Arduino
Wired 08.07.2025
Bluetooth - это технология, созданная чтобы заменить кабельные соединения. Обычно ее используют для связи небольших устройств: мобильных телефонов, ноутбуков, наушников и т. д. Работает она на частоте. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru