Аналог windows h в с

Обновлено: 05.07.2024

Как известно, концепция сокетов была разработана в Беркли, и затем реализована сначала в BSD, затем в Linux и, наконец, с некоторыми изменениями, и в Windows. Таким образом, это делает сетевое программирование на обеих платформах очень сильно похожим и перенос Unix приложения на Win-платформу становится не очень сложным делом.

Эта статья - попытка помочь тем, кто впервые решил осуществить порт сокетного приложения из Unix (Linux, BSD) в Windows. Зачем? Кто-то решает поднять свой уровень кодинга на новую высоту, кому-то это просто интересно, а кто-то ищет новые задачи для решения. Совет: не пытайтесь сразу портировать что-нибудь достаточно большое и сложное, начните с простых утилит вроде traceroute, nslookup и с прочтения этой статьи :-). Базовых знаний приемов сетевого программирования на C++ будет вполне достаточно. Все примеры из статьи компилировались на VC++ 6.0 под Win2k prof. и WinXP prof.

Unix и Windows

UNIX и Windows по разному обращаются с сокетами: в UNIX сокеты обрабатываются системой точно так же, как дескрипторы файлов integer типа, в то время как Windows это хэндл unsigned типа - SOCKET. В Unix все I/O действия выполняются чтением или записью в соответствующий дескриптор - число (integer) ассоциированное с открытым файлом, сетевым соединением, терминалом и т.п.

В Unix коды ошибок доступны через переменную errno, в Windows нужно использовать функцию WSAGetLastError().

И в Unix и в Windows порт определяется параметром, переданном функции htons(), но в Windows некоторые, наиболее часто используемые порты предопределены в
winsock.h:

IPPORT_ECHO - 7
IPPORT_DISCARD - 9
IPPORT_SYSTAT - 11
IPPORT_DAYTIME - 13
IPPORT_NETSTAT - 15
IPPORT_FTP - 21
IPPORT_TELNET - 23
IPPORT_SMTP - 25
IPPORT_TIMESERVER - 37
IPPORT_NAMESERVER - 42
IPPORT_WHOIS - 43
IPPORT_MTP - 57

Заголовочные файлы
Вот список функций Unix и соответствующих им .h-файлов

Эти два файла к сокетам не относятся, но обычно присутствуют в Unix программах:

Т.е. типичное начало сетевой UNIX программы выглядит так:

При переносе в Windows, все эти строки заменяются на одну:

Объявление winsock.h уже включено в windows.h.

Вторым шагом будет линковка приложению Wsock32.lib (Для VC++: меню Project->Settings, на вкладке Link, дописать wsock32.lib к списку библиотек).

UNIX и Windows имеют ряд общих, выполняющих одинаковые функций
процедур. Это большинство функций работы с TCP/UDP, все функции преобразования + используемые ими структуры. Это, например, функции htons() и inet_addr() и структуры sockaddr и sockaddr_in.

Вот список этих функций:
socket()
bind()
listen()
connect()
accept()
sendto()
recvfrom()
gethostname()

А вот список функций, делающих одно и то же, различающихся только названиями:

Unix Windows
close() closesocket()
ioctl() ioctlsocket()
read() recv()
write() send()

Дополнительно к вышесказанному, каждое сокетное приложение Windows должно содержать вызовы функций WSASStartup() и WSACleanup(), которые подготавливают к использованию Winsock и освобождают его, соответственно.

Для начала, перенесем что-нибудь простенькое. Например утилиту, определяющую IP-адрес хоста по его имени. Вот UNIX код:

int main(int argc, char *argv[])
<
struct hostent *he;

if ((he=gethostbyname(argv[1]))==NULL)
<
printf ("gethostbyname() error\n");
exit (-1);
>

printf ("Hostname : %s\n",he->h_name); /* Вывод имени хоста */
printf ("IP Address: %s\n",inet_ntoa(*((struct in_addr *)he->h_addr))); /* И его IP-адреса
*/
>

Попытка скомпилировать этот код без изменений была горячо воспринята VC++ - компилятор ругнулся на отсутствие .h файлов и сообщил, что компилировать программу он не собирается :-). Первым делом удаляем 2-5 строки, заменив их на:

и немного изменим строку 6:

void main(int argc, char **argv)

не забыв прилинковать wsock32.lib к проекту. Теперь программа компилируется без проблем, но при попытке ею воспользоваться выдает лаконичное: "gethostbyname() error". В чем дело? Все просто, не были вызваны WSAStartup() и WSACleanup()! Добавляем вызовы этих функций и код нормально компилируется.

Вот код портированного, работающего Win приложения:

void main(int argc, char **argv)
<
WSADATA wsdata;
WSAStartup(0x0101,&wsdata);
struct hostent *he;

if (argc! = 2)
<
printf("Usage: %s hostname\n",argv[0]);
>

if ((he = gethostbyname(argv[1])) == NULL)
<
printf("gethostbyname() error\n");
>

printf ("Hostname : %s\n",he->h_name);
printf("IP Address: %s\n",inet_ntoa(*((struct in_addr *)he->h_addr)));

Конечно, это - очень простое приложение. Попробуем перенести программу посложнее
- TCP streaming server.

main()
<
int fd, fd2; /* дескрипторы */
struct sockaddr_in server; /* информация о сервере */
struct sockaddr_in client; /* информация о клиенте */
int sin_size;

server.sin_family = AF_INET;
server.sin_port = htons (PORT);
server.sin_addr.s_addr = INADDR_ANY;
bzero (&(server.sin_zero),8);

if (bind(fd,(struct sockaddr*)&server, sizeof(struct sockaddr))==-1)
< /* вызов bind() */
printf ("bind() error\n");
exit (-1);
>

while (1)
<
sin_size=sizeof (struct sockaddr_in);
if ((fd2 = accept(fd,(struct sockaddr *)&client, &sin_size))==-1)
< /* вызов accept() */
printf ("accept() error\n");
exit (-1);
>

printf ("You got a connection from %s\n", inet_ntoa(client.sin_addr) );
send (fd2,"Welcome to my server.\n",22,0);
close (fd2);
>>

Итак, сначала повторим шаги из предыдущего примера - оставим объявления только windows.h и stdio.h и прилинкуем wsock32.lib. Попытка компиляции приносит две ошибки: одна - по поводу функции bzero(), вторая - по поводу функции
close() - компилятор сообщает, что она - invalid identifier :-). Первая ошибка лечится очень просто - удаляем всю 21-ю строку. Для исправления второй, смотрим в таблицу, приведенную выше и заменяем close() на ее Win-аналог - closesocket(). Добавляем вызовы WSAStartup() и WSACleanup() и voila - программа компилируется без проблем. После запуска программы видим пустую командную строку, все правильно - сервер ждет клиента :-).

Windows код сервера:

main()
<
WSADATA wsdata;
WSAStartup(0x0101,&wsdata);

struct sockaddr_in server;
struct sockaddr_in client;
int sin_size;

if ((fd=socket(AF_INET, SOCK_STREAM, 0)) == -1 )
<
printf("socket() error\n");
exit(-1);
>

server.sin_family = AF_INET;
server.sin_port = htons(PORT);
server.sin_addr.s_addr = INADDR_ANY;

if (bind(fd,(struct sockaddr*)&server, sizeof(struct sockaddr))==-1)
<
printf ("bind() error\n");
exit (-1);
>

if (listen (fd,BACKLOG) == -1)
<
printf ("listen() error\n");
exit (-1);
>

while (1)
<
sin_size=sizeof (struct sockaddr_in);

if ((fd2 = accept(fd,(struct sockaddr *)&client,&sin_size)) == -1)
<
printf ("accept() error\n");
exit (-1);
>

printf ("You got a connection from %s\n",inet_ntoa(client.sin_addr) );
send (fd2,"Welcome to my server.\n",22,0);
closesocket (fd2);

TCP streaming client

int main (int argc, char *argv[])
<
int fd, numbytes; /* дескрипторы */
char buf[MAXDATASIZE]; /* здесь будем хранить полученный текст */

struct hostent *he;
struct sockaddr_in server;

if ((he=gethostbyname(argv[1]))==NULL)
<
printf("gethostbyname() error\n");
exit(-1);
>

if ((fd=socket(AF_INET, SOCK_STREAM, 0))==-1)
<
printf("socket() error\n");
exit(-1);
>

server.sin_family = AF_INET;
server.sin_port = htons(PORT);
server.sin_addr = *((struct in_addr *)he->h_addr);
bzero(&(server.sin_zero),8);

if(connect(fd, (struct sockaddr *)&server,sizeof(struct sockaddr))==-1)
<
printf("connect() error\n");
exit(-1);
>

if ((numbytes=recv(fd,buf,MAXDATASIZE,0)) == -1)
<
printf("recv() error\n");
exit(-1);
>
buf[numbytes]='\0';
printf("Server Message: %s\n",buf);
close(fd);
>

И, без лишних слов, Windows код - для его получения нужно проделать те же, вышеописанные, шаги.

int main(int argc, char *argv[])
<
WSADATA wsdata;
WSAStartup(0x0101,&wsdata);
int fd, numbytes;
char buf[MAXDATASIZE];
struct hostent *he;
struct sockaddr_in server;

if (argc !=2)
printf("Usage: %s <IP Address>\n",argv[0]);
exit(-1);
>

if ((he=gethostbyname(argv[1])) == NULL)
printf("gethostbyname() error\n");
exit(-1);
>

if ((fd=socket(AF_INET, SOCK_STREAM, 0))==-1)
<
printf("socket() error\n");
exit(-1);
>

server.sin_family = AF_INET;
server.sin_port = htons(PORT);
server.sin_addr = *((struct in_addr *)he->h_addr);

if(connect(fd, (struct sockaddr *)&server,sizeof(struct sockaddr))==-1)
<
printf("connect() error\n");
exit(-1);
>

if ((numbytes=recv(fd,buf,MAXDATASIZE,0)) == -1)
<
printf("recv() error\n");
exit(-1);
>

buf[numbytes] = '\0';
printf("Server Message: %s\n",buf);
closesocket(fd);
WSACleanup();
return -1;
>

Запустив клиента (при запущенном сервере, естественно) с аргументом localhost (что-то вроде tcp_client.exe localhost) видим приветствие сервера - "Welcome to my server". С чем я тебя и поздравляю
:-).

Вот те шаги, которые нужно делать в первую очередь, при переносе приложений:

1. Заменить объявления заголовочных файлов UNIX на windows.h и прилинковать wsock32.lib
2. Добавить вызовы функций WSAStartup() и WSACleanup()
3. Заменить функции вроде close() и ioctl() на их Windows-аналоги

Можно даже написать небольшую программу делающую это автоматически (например на Perl). Она здорово облегчит процесс порта приложений.

Здравствуйте,уважаемое комюнити! Извиняюсь за ламерский смахивающий на баш вопрос,но все же. как сделать так,чтобы в code::blocks 10.5 можно было подключать <windows.h> и прочее из вендов. И если у кого есть, поделитесь пжл маном по настройке code::blocks.. Буду очень благодарен за помощь!





Учусь кодить. но под вендой в Visual Studio сидеть не очень хоца. а иногда приходится использовать вендовые библиотеки.



можно-то можно,но вот code::blocks всячески кричит что незнает такого.


>а иногда приходится использовать вендовые библиотеки.

В Linux-то? А какие например? На худой случай есть winelib


> Учусь кодить.

Это хорошо.

но под вендой в Visual Studio сидеть не очень хоца.


Ты уже выбрал code::blocks, так что VS не нужен.

а иногда приходится использовать вендовые библиотеки.


> В Linux-то? А какие например? На худой случай есть winelib


А нахер? Я даже под вендой не использую вендовых библиотек :)



я пробую пока писать консольные проги.
вот к примеру такой код:


чтобы все разукрасить используется windows.h
а как тогда сделать так, чтобы в консоле линя все получилось так как в венде,я имею ввиду оформление


Инклудь свой windows.h как раньше, просто укажи в путях хедеров wine/include (или как уж там надо сейчас, я хз, той статье 7 лет)


>чтобы все разукрасить используется windows.h

У нас так не принято. Переписывай на curses или (в простых случаях) используй escape-последовательности

Потдскажите какие строчки поменять\добавить?
вот на эту

вот так ругается

тут кое-что поменял

но вот так ругается на последние 3 строчки.

тут несоответствие параметров

_________
Заранее благодарен!

Здравствуйте, Аноним, Вы писали:

такого файла в windows нет
а что там такое?

>тут кое-что поменял

с этим надо разбираться отдельно но по всей видимости это обычные трейсы
для начала заменить на обычный printf или OutputDebugString

Здравствуйте, Аноним, Вы писали:

А>Потдскажите какие строчки поменять\добавить?

Потому что это в Posix системах такая вещь: unistd.h

Дальше и смотреть особо не стал. Если программа активно работает с системой, а не только через стандартные функции C/C++ вам надо понимать, что она делает в linux и как можно перенести в windows. Механический подход, скорее всего, не прокатит. Некоторые posix-вещи не имеют прямых аналогов в windows, самая известная — fork() и требуют переписывания.

Могу ещё сказать, что если вы пытаетесь перенести какую-то более-менее известную OpenSource-программу, есть смысл поискать получше, скорее всего уже кто-то её портировал

Здравствуйте, Аноним, Вы писали:

А>Потдскажите какие строчки поменять\добавить?
А>вот на эту
.

Если надо быстро пользуй cygwin.

ecли проект не ширпотребный, то можешь попробовать interix (Subsystem For UNIX Applications), там POSIX с forkом и все твои headerы есть.

Необходим для работы с разделяемыми динамически-загружаемыми библиотеками.

Скорее всего, вам достаточно уже подключенных windows.h и winsock2.h. Как вам уже посоветовали, комментируете отсутствующие в Win32-среде *.h , а далее смотрите на какие отсутствующие декларации функций ругается компилятор. Лезете в документацию по Linux/Posix, читаете что они делают и пытаетесь припомнить аналог в Win32.

У меня такое впечатление, что вы хотите как-то по-быстрому запихать linux-программу в Windows. Весьма вероятно, ничего хорошего не выйдет, программирование для linux и для windows имеют достаточно много отличий, чтобы потребовалось переписать около 20%-30% слоя кода, тесно завязанного на систему.

Могу присоединиться к совету использовать Cygwin или MinGW, если вам требуется быстро скомпилировать и заставить работать в Windows линуксовый код.

Cygwin — добавляет в Windows библиотеки и окружение, реализующие posix-вызовы, создавая Unix внутри Windows. Часто самый простой способ заставить работать linux-программу в Windows, часто достаточно её просто скомпилировать в Cygwin. Но для работы, очень возможно, будет необходим установленный Cygwin, хотя может оказаться достаточно некоторых dll от него.

MinGW + MSys — порт компилятора gcc и shell-окружения в Windows. В отличие от Cygwin, откомпилированные в MinGW + MSys программы работают с windows-окружением и не требуют MSys для своей работы. Возможно, потребуется некоторая доработка.

там остальные тоже есть, см. /usr/include и ищите по именам файлов в %WINDIR%\SUA.

Я портирую относительно простую консольную программу, написанную для Unix, на платформу Windows (Visual c/" >C++ 8.0). Все исходные файлы включают " unistd.х", которого не существует. Удаляя его, я получаю жалобы на неправильные прототипы для "srandom", "random" и "getopt". Я знаю, что могу заменить случайные функции, и я уверен, что могу найти/взломать реализацию getopt.

но я уверен, что другие столкнулись с той же проблемой. Мой вопрос: есть ли портвейн " unistd.h " к окнам? По крайней мере, один containg тех функций, которые имеют собственную реализацию Windows - мне не нужны трубы или разветвления.

редактировать:

Я знаю, что могу создать свой собственный "unistd.h", который содержит замены для вещей, которые мне нужны, особенно в этом случае, поскольку это ограниченный набор. Но поскольку это кажется общей проблемой, мне было интересно, сделал ли кто-то работу уже для большего подмножества функциональность.

переключение на другой компилятор или среду невозможно на работе - я застрял в Visual Studio.

поскольку мы не можем найти версию в Интернете, давайте начнем здесь.
Большинство портов для Windows, вероятно, требуется только подмножество полного файла Unix.
Вот отправная точка. При необходимости добавьте определения.

попробуйте включить . Кажется, это эквивалент Visual Studio unistd.h .

надеюсь, это поможет.

Я бы рекомендовал использовать по MinGW/префикса msys как среда разработки. Особенно, если вы переносите простые консольные программы. Msys реализует Unix-подобную оболочку в Windows, а mingw-порт коллекция компиляторов GNU (GCC) и другие инструменты сборки GNU для платформы Windows. Это проект с открытым исходным кодом и хорошо подходит для этой задачи. В настоящее время я использую его для создания утилит и консольных приложений для Windows XP, и у него, безусловно, есть это

я наткнулся на эту тему, пытаясь найти альтернативу Windows для getpid() (определена в unistd.h ). Оказывается, что в том числе process.h делает трюк. Возможно, это поможет людям, которые найдут эту нить в будущем.

нет, IIRC нет getopt () на Windows.

Boost, однако, имеет program_options библиотека. что работает нормально. Сначала это покажется излишним, но это не страшно, особенно учитывая, что он может обрабатывать параметры настройки программы в файлах конфигурации и переменных среды в дополнение к параметрам командной строки.

создайте свой собственный unistd.H заголовок и включить необходимые заголовки для прототипов функций.

Читайте также: