информационная безопасность
без паники и всерьез
 подробно о проектеRambler's Top100
За кого нас держат?Где водятся OGRыСтрашный баг в Windows
BugTraq.Ru
Русский BugTraq
 Анализ криптографических сетевых... 
 Модель надежности двухузлового... 
 Специальные марковские модели надежности... 
 Бэкдор в xz/liblzma, предназначенный... 
 Три миллиона электронных замков... 
 Doom на газонокосилках 
главная обзор RSN блог библиотека закон бред форум dnet о проекте
bugtraq.ru / форум / programming
Имя Пароль
ФОРУМ
если вы видите этот текст, отключите в настройках форума использование JavaScript
регистрация





Легенда:
  новое сообщение
  закрытая нитка
  новое сообщение
  в закрытой нитке
  старое сообщение
  • Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
  • Новичкам также крайне полезно ознакомиться с данным документом.
Пример на WSAAsyncSelect 28.04.03 10:38  Число просмотров: 6412
Автор: ukv Статус: Незарегистрированный пользователь
<"чистая" ссылка>
// Module Name: asyncselect.cpp
//
// Description:
//
// This sample illustrates how to develop a simple echo server Winsock
// application using the WSAAsyncSelect() I/O model. This sample is
// implemented as a console-style application (to reduce the programming
// complexity of writing a real Windows application) and simply prints
// messages when connections are established and removed from the server.
// The application listens for TCP connections on port 5150 and accepts them
// as they arrive. When this application receives data from a client, it
// simply echos (this is why we call it an echo server) the data back in
// it's original form until the client closes the connection.
//
// Since the WSAAsyncSelect I/O model requires an application to manage
// window messages when network event occur, this application creates
// a window for the I/O model only. The window stays hidden during the
// entire execution of this application.
//
// Compile:
//
// cl -o asyncselect asyncselect.cpp ws2_32.lib user32.lib gdi32.lib
//

#include <winsock2.h>
#include <windows.h>
#include <stdio.h>
#include <conio.h>

#define PORT 5150
#define DATA_BUFSIZE 8192

typedef struct _SOCKET_INFORMATION {
BOOL RecvPosted;
CHAR Buffer[DATA_BUFSIZE];
WSABUF DataBuf;
SOCKET Socket;
DWORD BytesSEND;
DWORD BytesRECV;
_SOCKET_INFORMATION *Next;
} SOCKET_INFORMATION, * LPSOCKET_INFORMATION;

#define WM_SOCKET (WM_USER + 1)

void CreateSocketInformation(SOCKET s);
LPSOCKET_INFORMATION GetSocketInformation(SOCKET s);
void FreeSocketInformation(SOCKET s);

HWND MakeWorkerWindow(void);
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

LPSOCKET_INFORMATION SocketInfoList;

void main(void)
{
MSG msg;
DWORD Ret;
SOCKET Listen;
SOCKADDR_IN InternetAddr;
HWND Window;
WSADATA wsaData;

if ((Window = MakeWorkerWindow()) == NULL)
return;

// Prepare echo server

if ((Ret = WSAStartup(0x0202, &wsaData)) != 0)
{
printf("WSAStartup failed with error %d\n", Ret);
return;
}

if ((Listen = socket (PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
{
printf("socket() failed with error %d\n", WSAGetLastError());
return;
}

WSAAsyncSelect(Listen, Window, WM_SOCKET, FD_ACCEPT|FD_CLOSE);

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

if (bind(Listen, (PSOCKADDR) &InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR)
{
printf("bind() failed with error %d\n", WSAGetLastError());
return;
}

if (listen(Listen, 5))
{
printf("listen() failed with error %d\n", WSAGetLastError());
return;
}

// Translate and dispatch window messages for the application thread

while(Ret = GetMessage(&msg, NULL, 0, 0))
{
if (Ret == -1)
{
printf("GetMessage() failed with error %d\n", GetLastError());
return;
}

TranslateMessage(&msg);
DispatchMessage(&msg);
}
}


LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
SOCKET Accept;
LPSOCKET_INFORMATION SocketInfo;
DWORD RecvBytes, SendBytes;
DWORD Flags;

if (uMsg == WM_SOCKET)
{
if (WSAGETSELECTERROR(lParam))
{
printf("Socket failed with error %d\n", WSAGETSELECTERROR(lParam));
FreeSocketInformation(wParam);
}
else
{
switch(WSAGETSELECTEVENT(lParam))
{
case FD_ACCEPT:

if ((Accept = accept(wParam, NULL, NULL)) == INVALID_SOCKET)
{
printf("accept() failed with error %d\n", WSAGetLastError());
break;
}

// Create a socket information structure to associate with the
// socket for processing I/O.

CreateSocketInformation(Accept);

printf("Socket number %d connected\n", Accept);

WSAAsyncSelect(Accept, hwnd, WM_SOCKET, FD_READ|FD_WRITE|FD_CLOSE);

break;

case FD_READ:

SocketInfo = GetSocketInformation(wParam);

// Read data only if the receive buffer is empty.

if (SocketInfo->BytesRECV != 0)
{
SocketInfo->RecvPosted = TRUE;
return 0;
}
else
{
SocketInfo->DataBuf.buf = SocketInfo->Buffer;
SocketInfo->DataBuf.len = DATA_BUFSIZE;

Flags = 0;
if (WSARecv(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &RecvBytes,
&Flags, NULL, NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != WSAEWOULDBLOCK)
{
printf("WSARecv() failed with error %d\n", WSAGetLastError());
FreeSocketInformation(wParam);
return 0;
}
}
else // No error so update the byte count
{
SocketInfo->BytesRECV = RecvBytes;
}
}

// DO NOT BREAK HERE SINCE WE GOT A SUCCESSFUL RECV. Go ahead
// and begin writing data to the client.

case FD_WRITE:

SocketInfo = GetSocketInformation(wParam);

if (SocketInfo->BytesRECV > SocketInfo->BytesSEND)
{
SocketInfo->DataBuf.buf = SocketInfo->Buffer + SocketInfo->BytesSEND;
SocketInfo->DataBuf.len = SocketInfo->BytesRECV - SocketInfo->BytesSEND;

if (WSASend(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &SendBytes, 0,
NULL, NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != WSAEWOULDBLOCK)
{
printf("WSASend() failed with error %d\n", WSAGetLastError());
FreeSocketInformation(wParam);
return 0;
}
}
else // No error so update the byte count
{
SocketInfo->BytesSEND += SendBytes;
}
}

if (SocketInfo->BytesSEND == SocketInfo->BytesRECV)
{
SocketInfo->BytesSEND = 0;
SocketInfo->BytesRECV = 0;

// If a RECV occurred during our SENDs then we need to post an FD_READ
// notification on the socket.

if (SocketInfo->RecvPosted == TRUE)
{
SocketInfo->RecvPosted = FALSE;
PostMessage(hwnd, WM_SOCKET, wParam, FD_READ);
}
}

break;

case FD_CLOSE:

printf("Closing socket %d\n", wParam);
FreeSocketInformation(wParam);

break;
}
}
return 0;
}

return DefWindowProc(hwnd, uMsg, wParam, lParam);
}


void CreateSocketInformation(SOCKET s)
{
LPSOCKET_INFORMATION SI;

if ((SI = (LPSOCKET_INFORMATION) GlobalAlloc(GPTR,
sizeof(SOCKET_INFORMATION))) == NULL)
{
printf("GlobalAlloc() failed with error %d\n", GetLastError());
return;
}

// Prepare SocketInfo structure for use.

SI->Socket = s;
SI->RecvPosted = FALSE;
SI->BytesSEND = 0;
SI->BytesRECV = 0;

SI->Next = SocketInfoList;

SocketInfoList = SI;
}

LPSOCKET_INFORMATION GetSocketInformation(SOCKET s)
{
SOCKET_INFORMATION *SI = SocketInfoList;

while(SI)
{
if (SI->Socket == s)
return SI;

SI = SI->Next;
}

return NULL;
}

void FreeSocketInformation(SOCKET s)
{
SOCKET_INFORMATION *SI = SocketInfoList;
SOCKET_INFORMATION *PrevSI = NULL;

while(SI)
{
if (SI->Socket == s)
{
if (PrevSI)
PrevSI->Next = SI->Next;
else
SocketInfoList = SI->Next;

closesocket(SI->Socket);
GlobalFree(SI);
return;
}

PrevSI = SI;
SI = SI->Next;
}
}

HWND MakeWorkerWindow(void)
{
WNDCLASS wndclass;
CHAR *ProviderClass = "AsyncSelect";
HWND Window;

wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = (WNDPROC)WindowProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = NULL;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = ProviderClass;

if (RegisterClass(&wndclass) == 0)
{
printf("RegisterClass() failed with error %d\n", GetLastError());
return NULL;
}

// Create a window.

if ((Window = CreateWindow(
ProviderClass,
"",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
NULL,
NULL)) == NULL)
{
printf("CreateWindow() failed with error %d\n", GetLastError());
return NULL;
}

return Window;
}
<programming>
[Net] Асинхронные/неблокирующие сокеты 27.04.03 07:37  
Автор: Drow Elf Статус: Незарегистрированный пользователь
<"чистая" ссылка>
Если не очень тяжело, объясните, как с помощью ioctlsocket (в winsock) сделать неблокирующие сокеты, в смысле как разблокировать сокет с помощью этой функции я знаю, но как с помощью select в последствии проверять статус, что-то не очень понятно :(
Кстати есть ли принципиальная разница между асинхронными сокетами(WSA) и неблокирующими......... Thanks
Пример на WSAAsyncSelect 28.04.03 10:38  
Автор: ukv Статус: Незарегистрированный пользователь
<"чистая" ссылка>
// Module Name: asyncselect.cpp
//
// Description:
//
// This sample illustrates how to develop a simple echo server Winsock
// application using the WSAAsyncSelect() I/O model. This sample is
// implemented as a console-style application (to reduce the programming
// complexity of writing a real Windows application) and simply prints
// messages when connections are established and removed from the server.
// The application listens for TCP connections on port 5150 and accepts them
// as they arrive. When this application receives data from a client, it
// simply echos (this is why we call it an echo server) the data back in
// it's original form until the client closes the connection.
//
// Since the WSAAsyncSelect I/O model requires an application to manage
// window messages when network event occur, this application creates
// a window for the I/O model only. The window stays hidden during the
// entire execution of this application.
//
// Compile:
//
// cl -o asyncselect asyncselect.cpp ws2_32.lib user32.lib gdi32.lib
//

#include <winsock2.h>
#include <windows.h>
#include <stdio.h>
#include <conio.h>

#define PORT 5150
#define DATA_BUFSIZE 8192

typedef struct _SOCKET_INFORMATION {
BOOL RecvPosted;
CHAR Buffer[DATA_BUFSIZE];
WSABUF DataBuf;
SOCKET Socket;
DWORD BytesSEND;
DWORD BytesRECV;
_SOCKET_INFORMATION *Next;
} SOCKET_INFORMATION, * LPSOCKET_INFORMATION;

#define WM_SOCKET (WM_USER + 1)

void CreateSocketInformation(SOCKET s);
LPSOCKET_INFORMATION GetSocketInformation(SOCKET s);
void FreeSocketInformation(SOCKET s);

HWND MakeWorkerWindow(void);
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

LPSOCKET_INFORMATION SocketInfoList;

void main(void)
{
MSG msg;
DWORD Ret;
SOCKET Listen;
SOCKADDR_IN InternetAddr;
HWND Window;
WSADATA wsaData;

if ((Window = MakeWorkerWindow()) == NULL)
return;

// Prepare echo server

if ((Ret = WSAStartup(0x0202, &wsaData)) != 0)
{
printf("WSAStartup failed with error %d\n", Ret);
return;
}

if ((Listen = socket (PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
{
printf("socket() failed with error %d\n", WSAGetLastError());
return;
}

WSAAsyncSelect(Listen, Window, WM_SOCKET, FD_ACCEPT|FD_CLOSE);

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

if (bind(Listen, (PSOCKADDR) &InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR)
{
printf("bind() failed with error %d\n", WSAGetLastError());
return;
}

if (listen(Listen, 5))
{
printf("listen() failed with error %d\n", WSAGetLastError());
return;
}

// Translate and dispatch window messages for the application thread

while(Ret = GetMessage(&msg, NULL, 0, 0))
{
if (Ret == -1)
{
printf("GetMessage() failed with error %d\n", GetLastError());
return;
}

TranslateMessage(&msg);
DispatchMessage(&msg);
}
}


LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
SOCKET Accept;
LPSOCKET_INFORMATION SocketInfo;
DWORD RecvBytes, SendBytes;
DWORD Flags;

if (uMsg == WM_SOCKET)
{
if (WSAGETSELECTERROR(lParam))
{
printf("Socket failed with error %d\n", WSAGETSELECTERROR(lParam));
FreeSocketInformation(wParam);
}
else
{
switch(WSAGETSELECTEVENT(lParam))
{
case FD_ACCEPT:

if ((Accept = accept(wParam, NULL, NULL)) == INVALID_SOCKET)
{
printf("accept() failed with error %d\n", WSAGetLastError());
break;
}

// Create a socket information structure to associate with the
// socket for processing I/O.

CreateSocketInformation(Accept);

printf("Socket number %d connected\n", Accept);

WSAAsyncSelect(Accept, hwnd, WM_SOCKET, FD_READ|FD_WRITE|FD_CLOSE);

break;

case FD_READ:

SocketInfo = GetSocketInformation(wParam);

// Read data only if the receive buffer is empty.

if (SocketInfo->BytesRECV != 0)
{
SocketInfo->RecvPosted = TRUE;
return 0;
}
else
{
SocketInfo->DataBuf.buf = SocketInfo->Buffer;
SocketInfo->DataBuf.len = DATA_BUFSIZE;

Flags = 0;
if (WSARecv(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &RecvBytes,
&Flags, NULL, NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != WSAEWOULDBLOCK)
{
printf("WSARecv() failed with error %d\n", WSAGetLastError());
FreeSocketInformation(wParam);
return 0;
}
}
else // No error so update the byte count
{
SocketInfo->BytesRECV = RecvBytes;
}
}

// DO NOT BREAK HERE SINCE WE GOT A SUCCESSFUL RECV. Go ahead
// and begin writing data to the client.

case FD_WRITE:

SocketInfo = GetSocketInformation(wParam);

if (SocketInfo->BytesRECV > SocketInfo->BytesSEND)
{
SocketInfo->DataBuf.buf = SocketInfo->Buffer + SocketInfo->BytesSEND;
SocketInfo->DataBuf.len = SocketInfo->BytesRECV - SocketInfo->BytesSEND;

if (WSASend(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &SendBytes, 0,
NULL, NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != WSAEWOULDBLOCK)
{
printf("WSASend() failed with error %d\n", WSAGetLastError());
FreeSocketInformation(wParam);
return 0;
}
}
else // No error so update the byte count
{
SocketInfo->BytesSEND += SendBytes;
}
}

if (SocketInfo->BytesSEND == SocketInfo->BytesRECV)
{
SocketInfo->BytesSEND = 0;
SocketInfo->BytesRECV = 0;

// If a RECV occurred during our SENDs then we need to post an FD_READ
// notification on the socket.

if (SocketInfo->RecvPosted == TRUE)
{
SocketInfo->RecvPosted = FALSE;
PostMessage(hwnd, WM_SOCKET, wParam, FD_READ);
}
}

break;

case FD_CLOSE:

printf("Closing socket %d\n", wParam);
FreeSocketInformation(wParam);

break;
}
}
return 0;
}

return DefWindowProc(hwnd, uMsg, wParam, lParam);
}


void CreateSocketInformation(SOCKET s)
{
LPSOCKET_INFORMATION SI;

if ((SI = (LPSOCKET_INFORMATION) GlobalAlloc(GPTR,
sizeof(SOCKET_INFORMATION))) == NULL)
{
printf("GlobalAlloc() failed with error %d\n", GetLastError());
return;
}

// Prepare SocketInfo structure for use.

SI->Socket = s;
SI->RecvPosted = FALSE;
SI->BytesSEND = 0;
SI->BytesRECV = 0;

SI->Next = SocketInfoList;

SocketInfoList = SI;
}

LPSOCKET_INFORMATION GetSocketInformation(SOCKET s)
{
SOCKET_INFORMATION *SI = SocketInfoList;

while(SI)
{
if (SI->Socket == s)
return SI;

SI = SI->Next;
}

return NULL;
}

void FreeSocketInformation(SOCKET s)
{
SOCKET_INFORMATION *SI = SocketInfoList;
SOCKET_INFORMATION *PrevSI = NULL;

while(SI)
{
if (SI->Socket == s)
{
if (PrevSI)
PrevSI->Next = SI->Next;
else
SocketInfoList = SI->Next;

closesocket(SI->Socket);
GlobalFree(SI);
return;
}

PrevSI = SI;
SI = SI->Next;
}
}

HWND MakeWorkerWindow(void)
{
WNDCLASS wndclass;
CHAR *ProviderClass = "AsyncSelect";
HWND Window;

wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = (WNDPROC)WindowProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = NULL;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = ProviderClass;

if (RegisterClass(&wndclass) == 0)
{
printf("RegisterClass() failed with error %d\n", GetLastError());
return NULL;
}

// Create a window.

if ((Window = CreateWindow(
ProviderClass,
"",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
NULL,
NULL)) == NULL)
{
printf("CreateWindow() failed with error %d\n", GetLastError());
return NULL;
}

return Window;
}
[Net] Всегда считал, что асинхронные и есть неблокирующие 27.04.03 14:06  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
Неправильно ты считал. 06.05.03 17:57  
Автор: L Статус: Незарегистрированный пользователь
<"чистая" ссылка>
а как тогда правильно? 07.05.03 08:32  
Автор: Killer{R} <Dmitry> Статус: Elderman
<"чистая" ссылка>
цитата из МСДНа:
The WSAAsyncSelect function automatically sets socket s to nonblocking mode, regardless of the value of lEvent. See the ioctlsocket functions for information on how to set the nonblocking socket back to blocking mode.
а как тогда правильно? 07.05.03 12:34  
Автор: L Статус: Незарегистрированный пользователь
<"чистая" ссылка>
Читай контекст:
Автор> Кстати есть ли принципиальная разница между асинхронными сокетами(WSA) и неблокирующими

amirul>Всегда считал, что асинхронные и есть неблокирующие

Правильный ответ: не путать тёплое с мягким. Между асинхронными сокетами и non-blocking mode как раз такипринципиальнаяразница.
По понятиям 08.05.03 12:14  
Автор: IgorR <Igor Razin> Статус: Member
<"чистая" ссылка>
> Читай контекст:
>Между асинхронными сокетами и non-blocking mode как раз таки
>принципиальнаяразница.

Асинхронные сокеты говоришь? Не слышал про такие.
Действительно, междусокетамии modeесть разница.

ЗЫ. Все 4 модели асинхронного ввода-вывода (без select-а) подразумевают неблокирующий режим работы сокета.
<без заголовка> 09.05.03 00:45  
Автор: L Статус: Незарегистрированный пользователь
<"чистая" ссылка>

> Асинхронные сокеты говоришь? Не слышал про такие.
Теоретик? Или жажда правды обуяла? На MSDN это весьма расхожее словосочетание для обозначения асинхронного в/в с использованием сокетов.

> Действительно, междусокетамии modeесть разница.
Ты практически точь-в-точь повторил мою фразу.

> ЗЫ. Все 4 модели асинхронного ввода-вывода (без select-а)
> подразумевают неблокирующий режим работы сокета.
Читай вопрос автора, ответ и моё замечание.
<без заголовка> 11.05.03 11:59  
Автор: IgorR <Igor Razin> Статус: Member
<"чистая" ссылка>
> Теоретик? Или жажда правды обуяла?
См ниже.

>Правильный ответ: не путать тёплое с мягким. Между асинхронными сокетами и non-blocking mode как раз такипринципиальнаяразница.
И это я ещё теоритик?

> > Действительно, междусокетамииmodeесть разница.
> Ты практически точь-в-точь повторил мою фразу.
Ту, что выше? Гы. Глумлюсь я ;)

> > ЗЫ. Все 4 модели асинхронного ввода-вывода (без
> select-а) подразумевают неблокирующий режим работы сокета.
> Читай вопрос автора, ответ и моё замечание.
Читал, прикинь?

Автор> Кстати есть ли принципиальная разница между асинхронными сокетами(WSA) и неблокирующими
amirul>Всегда считал, что асинхронные и есть неблокирующие
>Правильный ответ: не путать тёплое с мягким. Между асинхронными сокетами и non-blocking mode как раз такипринципиальнаяразница.
Твоё "замечание" абсолютно не в тему. Если есть что сказать по существу - говори, а так - выпендрёж.
<без заголовка> 13.05.03 03:21    Штраф: 30 [Ktirf, amirul]
Автор: L Статус: Незарегистрированный пользователь
<"чистая" ссылка>
> Ту, что выше? Гы. Глумлюсь я ;)
Проглумишься - возвращайся.
Я не врач из Кащенко, помочь ничем не могу.
<без заголовка> 09.05.03 01:04  
Автор: Killer{R} <Dmitry> Статус: Elderman
<"чистая" ссылка>
итак:
1)асинхронные сокеты это сокеты позволяющие проводить в\в асинхронно, то бишь независимо самой проги
2)неблокирующие сокеты - это сокеты которые не блокируют выполнение программы. достигаетмся это выполнением в\в параллельно самой проге

или я чегото неправильно понимаю, или это одно и то же. Аснхронные сокеты не блокируют прогу а неблокирующие работают асинхронно Ж)
Не говори загадками. Растолкуй эти понятия мне, ламеру бестолковому Ж) 07.05.03 17:13  
Автор: Killer{R} <Dmitry> Статус: Elderman
<"чистая" ссылка>
1




Rambler's Top100
Рейтинг@Mail.ru


  Copyright © 2001-2024 Dmitry Leonov   Page build time: 1 s   Design: Vadim Derkach