Идея

Идею управления компьютером с мобильника через WAP я ношу в голове уже пару лет,
а тут у меня появился Siemens M50, у которого имеется GPRS. Включил услугу
WAP через GPRS и начал работать. Первым делом, конечно, решил поискать уже
готовые решения, однако ничего путного, кроме RemotelyAnywhere v5.00.406 я не
нашел. Единственным недостатком этой софтины было использование WAP второй версии.
Большинство же сотовых, представленных сегодня на рынке, поддерживают WAP версии
не выше 1.2.1. Поэтому я и решил сам написать WAP-сервер для управления PCшником. 

Начнем

Кодить будем на MS Visual C++ 6.0 на уровне WinAPI, с использованием библиотеки
WinSock. Первым делом создадим новый проект и добавим в линковку две библиотеки: 

ws2_32.lib - библиотека Windows Sockets
winmm.lib - Multimedia библиотека

Добавляем Source-файл main.cpp и вставляем заголовки:

#include <windows.h> // Стандартно
#include <winsock.h> //
Сокеты
#include <mmsystem.h> //
Multimedia

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

#pragma comment(linker,"/MERGE:.rdata=.text")
#pragma comment(linker,"/FILEALIGN:512 /SECTION:.text,EWRX /IGNORE:4078")
#pragma comment(linker,"/ENTRY:MyWinMain") //
Точка входа
#pragma comment(linker,"/NODEFAULTLIB")

Немного теории

Согласно протоколу WAP (Wireless Application Proctocol), после отправления запроса
клиентом, сервер должен послать либо запрошенный документ с его типом
(WML- Wireless Markup Language) и кодом успешности операции
(200), либо сообщение с ошибкой. Мы полагаем, что запрос верный и будем всегда посылать меню с
возможными вариантами действий: Открыть/Закрыть лоток CD-ROMа, выключить или
перезагрузить компьютер и выйти из данного пользователя.
Для этого надо послать клиенту такие строки:

char s[12][62]=

"HTTP/1.1 200 OK\r\nContent-Type: text/vnd.wap.wml\r\n\r\n",
"<?xml version = \"1.0\"?>\r\n<!DOCTYPE wml PUBLIC \"-//WAPFORUM",
"//DTD WML 1.1//EN\" \"http://www.wapforum.org/DTD/wml_1.1.xml\">",
"\r\n<wml>\r\n<card id=\"Card1\" title=\"My Computer\">\r\n<p>",
"<a href=\"opencd\">OpenCD</a><br/>\r\n",
"<a href=\"closecd\">CloseCD</a><br/>\r\n",
"<a href=\"shut\">Shut Down</a><br/>\r\n",
"<a href=\"reset\">Reset</a><br/>\r\n",
"<a href=\"logoff\">LogOFF</a><br/>\r\n",
"</p>\r\n</card>\r\n</wml>\r\n"
};

Надо заметить, что WML построен на базе XML. 

Теперь приступим к кодингу

Кодим

Для начала напишем несколько вспомогательных функций, которые понадобятся нам
позже, а может и потом вам в своих приложениях.
CRC (Код циклического контроля) мы будем использовать для идентификации команд,
ИМХО это очень удобно, а CRC проверен временем и обеспечивает хорошее рассеивание.

u_long crc32_table[256]; //Для хранения таблицы crc
#define CRC32_POLY 0xEDB88320; // С
тандартный полином

//Инициализируем crc
void init_crc32()
{
int i, j;
u_long c;
for (i = 0; i < 256; ++i)
{
for (c = i << 24, j = 8; j > 0; --j)
if(c & 0x80000000){c=(c << 1) ^ CRC32_POLY;} else {c=(c << 1);};
crc32_table[i] = c;
}
}

//Считаем CRC
u_long crc32(u_char *buf)
{
u_char *p= buf;
u_long crc;
crc = 0xffffffff;
while(*p!=0)
{
crc = (crc << 8) ^ crc32_table[(crc >> 24) ^ *(p++)];
if(*p==32) break;
};
return ~crc;
}

//Возвращает позицию n-ого пробела
int space(char * word, int n)
{
if(n==0) return -1;
int nbsp=0;
for(int i=0; i<strlen((char *)word); i++)
if(word[i]==32)
if(++nbsp==n) return i;
return -666;
}

//Возвращает n-ое слово word[0],
word[1],...

char temp[1000];
char * get(char * word, int n)
{
int j=0;
if(space(word, n)!=-666)
for(int i=space(word, n)+1; i<strlen(word); i++)
{
if(word[i]==32) break; else temp[j++]=word[i];
}
temp[j]=0;
return temp;
};

//Приводим английские символы в верхнему регистру
u_char * UpString(u_char * str)
{
int i=-1;
while(str[++i]!=0)
if((str[i]>96)&&(str[i]<123)) str[i]=str[i]&0xDF;
return str;
};

//Главная функция
void MyWinMain(void)
{
DWORD size, nr;
char Buff[1000];

//Инициалицируем crc32
init_crc32();

// Это для ведения логов
HANDLE out = CreateFile("C:\\dataxxx.txt", GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);

// Инициализируем и настраиваем сокет
WSADATA WSAData;
WSAStartup(MAKEWORD(1,1), &WSAData);
SOCKET Sock0 = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in name;
name.sin_family = AF_INET;
name.sin_port = htons(80); //
Будем ожидать подключения на 80-й порт
name.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(Sock0, (struct sockaddr FAR *) &name, sizeof(name))==SOCKET_ERROR)ExitProcess(666);

listen(Sock0, 5); // Слушаем

again:
SOCKET Sock1=accept(Sock0, NULL, NULL); //
Принимаем соединение

while(true)
{
ioctlsocket(Sock1, FIONREAD, &size); //
Пришел запрос?
if(size>0) //
Да!
{

recv(Sock1,(char *)Buff,1000,0); // Получаем запрос
WriteFile(out, &Buff, size, &nr, NULL); //
В лог

// Отправляем меню в сотик и в лог
for(int i=0; i<12; i++)
{
send(Sock1, s[i], strlen(s[i]), 0);
WriteFile(out, &s[i], strlen(s[i]), &nr, NULL);
}
closesocket(Sock1);

// Если REQUEST==GET
if( crc32(UpString( (u_char *)get(Buff, 0)))==0xA10411F )
switch( crc32(UpString( (u_char *)get(Buff, 1))) )
{
//
OPENCD
case 0x52AD375F:
mciSendString("SET CDAUDIO DOOR OPEN WAIT",0,0, 0); break;
//
CLOSECD
case 0x3918CCDF:
mciSendString("SET CDAUDIO DOOR CLOSED WAIT",0,0, 0); break;
//
SHUT
case 0xE4F1DC3F:
ExitWindowsEx(EWX_POWEROFF, 0); break;
//
RESET
case 0x54DF1B7F:
ExitWindowsEx(EWX_REBOOT, 0); break;
//
LOGOFF
case 0x838B5D5F:
ExitWindowsEx(EWX_LOGOFF, 0); break;
}

goto again;
}
};
CloseHandle(out);
}

Все, можно компилить (только в конфигурации Release) и запускать. Несчастливым
не обладателям сотовых могу лишь посоветовать воспользоваться WAP-эмулятором, коих
сейчас в сети полно. И еще, если вы хотите управлять компьютером через WEB-интерфейс, то вам надо лишь заменить отправляемое меню на такое:

char s[8][50]=

"HTTP/1.1 200 OK\r\nContent-Type: text/html;",
"charset=windows-1251\r\n\r\n",
"<html><title><<<FULL CONTROL>>></title><body>",
"<a href=\"opencd\">OpenCD</a><br>",
"<a href=\"closecd\">CloseCD</a><br>",
"<a href=\"reset\">Reset</a><br>",
"<a href=\"off\">OFF</a><br>",
"</body></html>"
};

Кому лень с этим разбираться могут скачать уже готовый
проект

Удачи!

  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    0 комментариев
    Межтекстовые Отзывы
    Посмотреть все комментарии