информационная безопасность
без паники и всерьез
 подробно о проектеRambler's Top100
Страшный баг в WindowsАтака на InternetСетевые кракеры и правда о деле Левина
BugTraq.Ru
Русский BugTraq
 Анализ криптографических сетевых... 
 Модель надежности двухузлового... 
 Специальные марковские модели надежности... 
 Очередное исследование 19 миллиардов... 
 Оптимизация ввода-вывода как инструмент... 
 Зловреды выбирают Lisp и Delphi 
главная обзор RSN блог библиотека закон бред форум dnet о проекте
bugtraq.ru / форум / programming
Имя Пароль
если вы видите этот текст, отключите в настройках форума использование JavaScript
ФОРУМ
все доски
FAQ
IRC
новые сообщения
site updates
guestbook
beginners
sysadmin
programming
operating systems
theory
web building
software
hardware
networking
law
hacking
gadgets
job
dnet
humor
miscellaneous
scrap
регистрация





Легенда:
  новое сообщение
  закрытая нитка
  новое сообщение
  в закрытой нитке
  старое сообщение
Пример на WSAAsyncSelect 28.04.03 10:38  Число просмотров: 6543
Автор: 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-2025 Dmitry Leonov   Page build time: 0 s   Design: Vadim Derkach