Вы уж извините,что так сразу,с такими вопросами тупыми врываюсь)
Решил попрактиковаться в работе с сетью и с сокетами,
выбор мой пал на создание примитивного mail.ru агента,
консольное приложение,которое может хотя бы могло законнектится к серверу,
и пройти авторизацию юзера.Сейчас опишу,как и что делаю.
Сначала подключаю winsock.2 и подгружаю библиотеку ws2_32.Lib
адрес и порт,по которому коннектится
#define PORT 2042
#define SERVERADDR "mrim.mail.ru"my_sock=socket(AF_INET,SOCK_STREAM,0);sockaddr_in dest_addr;
dest_addr.sin_family=AF_INET;
dest_addr.sin_port=htons(PORT);
HOSTENT *hst;hst=gethostbyname ( SERVERADDR );
( ( unsigned long * ) &dest_addr.sin_addr ) [ 0 ] =( ( unsigned long ** ) hst->h_addr_list ) [ 0 ] [ 0 ];connect(my_sock,(sockaddr*) &dest_addr,sizeof(dest_addr));#includeЗаголовок пакета
{
u_long magic; // Magic
u_long proto; // Версия протокола
u_long seq; // Sequence
u_long msg; // Тип пакета
u_long dlen; // Длина данных
u_long from; // Адрес отправителя
u_long fromport; // Порт отправителя
u_char reserved[16]; // Зарезервировано
}#define CS_MAGIC 0xDEADBEEF#define PROTO_VERSION_MAJOR 1
#define PROTO_VERSION_MINOR 7
#define PROTO_VERSION ((((u_long)(PROTO_VERSION_MAJOR))<<16)|(u_long)(PROTO_VERSION_MINOR))typedef struct mrim_packet_header_t
{
u_long magic; // Magic
u_long proto; // Версия протокола
u_long seq; // Sequence
u_long msg; // Тип пакета
u_long dlen; // Длина данных
u_long from; // Адрес отправителя
u_long fromport; // Порт отправителя
u_char reserved[16]; // Зарезервировано
}
mrim_packet_header_t;int send(SOCKET s,char* buf,int len,int flags);Ничего себе тренировочная задачка! ![]()
Судя по всему,
{
u_long magic; //волшебный ключ, указывающий на то, что это действительно пакет MMP
u_long proto; //версия MMP, поддерживаемая отправителем пакета
u_long seq; //номер отправляемой команды в текущем соединении. Ответ на команду должен иметь тот же номер, что и сама команда.
u_long msg; //тип пакета, номер команды и/или ответа
u_long dlen; //длина данных пакета (без учета заголовка)
u_long from; //ip (в inet_aton() формате) с которого установлено соединение
u_long fromport; //порт (в inet_aton() формате) с которого установлено соединение
u_char reserved[16];
}не,seq это просто номер команды,в ответе он должен быть таким же,короче это не очень важный параметр))
MRIM_CS_HELLO надо отправлять первым,указывая в msg.
отправить у меня получается,а вот в ответ приходит чет непонятное.
И потом как мне узнать,что пришло?
Если принять пакет с msg=MRIM_CS_HELLO_ACK,
то как принять mrim_connection_params_t ?
это же две разные структуры,и как мне они придут в одном ответе?
короче,как было ничего непонятно,так все и осталось)
лан,ща буду мучаться
ReindeeR
Каждый пакет состоит из заголовка (mrim_packet_header_t) и следующих за ними данных (зависят от команды, для MRIM_CS_HELLO_ACK - mrim_connection_params_t; для некоторых команд, типа MRIM_CS_HELLO - отсутствуют). Размер передаваемых данных нужно указывать в mrim_packet_header_t.dlen. Ну, это, я думаю, и так понятно ![]()
А ответ можно (и нужно) считывать за несколько приёмов. Сначала заголовок размером sizeof(mrim_packet_header_t), затем по считанному заголовку определяешь, какого типа данные ожидаются, создаёшь буфер соответствующего типа, и считываешь из сокета в него остаток пакета.
Как узнать что "вам пакет от сервера" - либо тупо ждать после отправки запроса, либо тоже самое, только умно - в отдельном потоке (thread) с контролем таймаута.
в ответ приходит какая-то фигня размеров в 19 байтов. ![]()
зы.причем один раз
ап.
mrim_connection_params_t 4 байта,
можно попробовать вынять эти 4 байта с начала или конца принятых 19 ![]()
зы.
а как это сделать?
ReindeeR
Могу поспорить, что эта фигня складывается в циферки типа "194.186.55.27:2041"
Новая проблемка))
не получается установить коннект с сервером.
Точнее получается,только не совсем правильно.
полученный адрес,по которому нужно соединятся с сервером,
находится в переменной IPaddr в формате "194.186.55.17:2041".
разделяю их с помощью strtok
ip=strtok(IPaddr,":");
port=strtok('\0',":");dest_addr.sin_family=AF_INET;
dest_addr.sin_addr.s_addr=inet_addr(ip);
dest_addr.sin_port=htons((u_short)port);С портом разобрался))
теперь проблема с приемом данных.
цитата из описания.
mrim_packet_header_t packHello;
packHello.magic=CS_MAGIC; //формирование пакета
packHello.proto=PROTO_VERSION;
packHello.seq=i;
packHello.msg=MRIM_CS_HELLO;
packHello.dlen=sizeof(mrim_packet_header_t);
packHello.from=0;
packHello.fromport=0;
send(my_sock,(char*)packHello,bufsize,0);//отправляется 44 байта,как и должно по идее.
//далее попытка принять пакет.
do
{
char *buffer;
int iResult=recv(mySock,buffer,bufsize,0);
if(iResult>0)
cout << "Размер полученных данных="<< iResult << endl;
else if(iResult==0)
cout << "Прием данных завершен.\n";
else
cout << WSAGetLastError() <<endl;
}while(iResult>0);packHello.from=0;
packHello.fromport=0;send(my_sock,(char*)packHello,bufsize,0);send(my_sock,(char*)&packHello,bufsize,0);packHello.dlen=0;mrim_packet_header_t buffer;
int iResult=recv(mySock, (char*)&buffer, bufsize, 0);
Так а в чём проблема?
mrim_packet_header_t header;
int iResult=recv(mySock, (char*)&header, sizeof(header), 0);
mrim_connection_params_t params;
iResult=recv(mySock, (char*)¶ms, sizeof(params), 0);
не знал,что так можно.
интервал получил,30 сек).
далее авторизация юзверя.
while (!quit) {
SendPing();
Sleep(30000);
}ыыы,авторизировался
)))
щас буду пробовать таймер установить.
Потоки=темный лес для меня пока что.
зы.
как синхронизировать все это,чтобы косяков не было? ![]()
ап.
Таймер использовать не получилось,так как он сразу убивается у меня.
Всмысле запускаю таймер,выполняется только первый раз при запуске,
а потом программа завершается,и абсолютно пофиг,что там таймер запущен.
ну а поток создать у меня тем более не получается.
ошибок вылезает хз скока.
Мне надо передать в функцию потока сокет и интервал пинга.
А если учитывать то,что про потоки я прочитал несколько часов назад,
для меня эта задача вообще невыполнимая
/* Acquire and dispatch messages until a WM_QUIT message is received. */
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}дело в том,что у меня приложение консольное,
цикл обработки сообщений никуда не запехаешь))
Ну не знаю, не знаю... Это - работает ![]()
ну тогда как передать мне в функцию tick() параметры?))
ап.
извиняюсь,как обычно туплю ![]()
void CALLBACK tick(HWND ccc,UINT iii,UINT aaa,DWORD bbb)mrim_packet_header_t packPing;
packPing.magic=CS_MAGIC;
packPing.proto=PROTO_VERSION;
packPing.seq=0;
packPing.msg=MRIM_CS_PING;
packPing.dlen=0;
packPing.from=0;
packPing.fromport=2041;
int iResult=send(my_sock,(char*)&packPing,sizeof(packPing),0);packPing.seq=0;и ноль,и не ноль пробовал.
зы.
наверное дело в том,что там еще заголовок стучиться+80 байт
оказалось это пришли данные о только что подсоединившеся юзвере,
его ник,сколько писем и т.д.Обнаружил чисто случайно это/
D описании протокола ниче по этому поводу не сказано,
типа после автризации к вам придет MRIM_CS_USER_INFO.
Или не влияет,что данные не все еще приняты и идет отправка?
ReindeeR
Пытаюсь получить информацию о пользователе.
Описание
iResult=recv(mySock,(char*)&bufSize,sizeof(bufSize),0);
cout << bufSize << endl;deadbeef
это че??
Ох-хо-хо...
#define CS_MAGIC 0xDEADBEEF // Клиентский Magic ( C <-> S )
мда..
Я когда прочитал deadbeef я чуть со стула не упал,
о том,что это они так мэджик обозначили мне и в голову уже придти не могло.
шутники мля..
я чето не понял.
пришел заголовок MRIM_CS_USER_INFO
размер пакета=80 байт.
принимаю данные,вдруг туда вклинивается заголовок MRIM_CS_USER_INFO
размер пакета=28 байт.
56 из обещанных 80 я принял,
80-56=24 байта еще должны по идее придти.
но приходит еще пакет размером размером 28.
итого перебор 4 байта.
Еще как я догадываюсь,скоро припрется контакт лист
зы.чуть не забыл.
после 56 байт приходит пакет MRIM_CS_USER_STATUS
Пакет: Смена статуса другого пользователя
Имя пакета: MRIM_CS_USER_STATUS
Тип пакета: sc
Параметры:
UL ## status ## новый статус пользователя ##
STATUS_OFFLINE ## Пользователь отключен от сети Агента
STATUS_ONLINE ## Пользователь находится в сети
STATUS_AWAY ## Пользователь в сети, но отошел от компьютера
STATUS_UNDETERMINATED ## Настройки пользователя запрещают показывать его статус
STATUS_FLAG_INVISIBLE ## Пользователь находится в сети, но невидим для всех, кроме привилегированных пользователей из его списка видимости.
LPS ## user ## email сменившего свой статус пользователя
Описание: Это сообщение отправляется сервером при смене статуса пользователям всем тем, у кого он находится в контакт-листе (за исключением группы "Жду Авторизации" и тех, кого он включил в список игнорируемых или невидящих). Данное сообщение может быть доставлено клиенту ДО получения им контакт-листа. В такой ситуации оно должно игнорироваться.А как полностью выглядит принятое по MRIM_CS_USER_INFO? (ник можно звёздочками)
iResult=recv(mySock,(char*)&packFrom,sizeof(packFrom),0); //Пришел пакет
if(iResult>0 && packFrom.msg == MRIM_CS_USER_INFO)
{
int sizeData=packFrom.dlen; //записываю скока байт обещают
int realSizeData=0; //в переменную будет дописываться размер принятых данных
iResult=recv(mySock,(char*)&bufSize,sizeof(bufSize),0); //в bufSize записываем длину следующей строки.
char msgTotal[4096];
iResult=recv(mySock,msgTotal,bufSize,0); //в переменной msgTotal будет строка "MESSAGES.TOTAL"
realSizeData+=iResult;
iResult=recv(mySock,(char*)&bufSize,sizeof(bufSize),0); //в bufSize записываем длину следующей строки.
char numMsgTotal[4096];
iResult=recv(mySock,numMsgTotal,bufSize,0); //приходит кол-во MESSAGES.TOTAL в виде строки.В моем случае это 81
realSizeData+=iResult;
printf("%s = %s\n",msgTotal,numMsgTotal);
iResult=recv(mySock,(char*)&bufSize,sizeof(bufSize),0);
char msgUnread[4096];
iResult=recv(mySock,msgUnread,bufSize,0); //строка "MESSAGES.UNREAD"
realSizeData+=iResult;
iResult=recv(mySock,(char*)&bufSize,sizeof(bufSize),0); //Количетсво непрочтенных писем
char numMsgUnread[4096];
iResult=recv(mySock,numMsgUnread,bufSize,0); //приходит кол-во MESSAGES.UNREAD в виде строки.В моем случае это 1
realSizeData+=iResult;
printf("%s = %s\n",msgUnread,numMsgUnread);
iResult=recv(mySock,(char*)&bufSize,sizeof(bufSize),0); //получаем строку "MRIM.NICKNAME
char nickName[4096];
iResult=recv(mySock,nickName,bufSize,0);
realSizeData+=iResult;
iResult=recv(mySock,(char*)&bufSize,sizeof(bufSize),0); //ну и получаем сам ник
char nick[4096];
iResult=recv(mySock,nick,bufSize,0);
realSizeData+=iResult;
printf("%s = %s \n",nickName,nick);
printf("Ожидаемый размер данных= %d \n Размер полученных данных = %d \n",sizeData,realSizeData); // чтобы сразу было видно.
}iResult=recv(mySock,(char*)&bufSize,sizeof(bufSize),0); //в bufSize записываем длину следующей строки.
realSizeData+=iResult; //<--- Добавить это. И так шесть раз. 6*4 = 24 "потерянных" байта
char msgTotal[4096];
iResult=recv(mySock,msgTotal,bufSize,0); //в переменной msgTotal будет строка "MESSAGES.TOTAL"
realSizeData+=iResult;char* msgTotal = (char*)malloc(bufSize+1);
msgTotal[bufSize]='\0';в том то и дело,
указываю меньше 4 кб,
всякая фигня оказывается в строке
Фигня, очевидно, показывается из-за того, что C/C++ понимает строки как массивы, завершающиеся нулём, а mail.ru их понимает как (4 байта длины)+(массив указанной длины, без нуля в конце).
ну ладно,это не так важно пока что.
что делать с этими пакетами,которые идут как-то не так.
щас попробую до конца все принять,пока не успокоятся))
Yason
вам памятник надо ставить за истреблении нубства в программировании.
спс огромное,дальше надеюсь сам разберусь уж как-нибудь.
Форум Invision Power Board (http://nulled.ws)
© Invision Power Services (http://nulled.ws)