Форум программистов, компьютерный форум, киберфорум
Наши страницы
C++ Builder
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.65/31: Рейтинг темы: голосов - 31, средняя оценка - 4.65
Programmer.
Прогер
631 / 262 / 15
Регистрация: 17.11.2010
Сообщений: 1,371
Записей в блоге: 2
#1

bind, listen функции не работают

21.02.2012, 05:39. Просмотров 5653. Ответов 63
Метки нет (Все метки)

Привет, ето опять я, шас я вбилдер пытаюс написать маленкий клиент и сервер(без компонентов сокета, не выходит, вот код и ощыбкы)

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
void __fastcall TForm47::Button1Click(TObject *Sender)
{
WSADATA data;
SOCKET sock;
int bind,listen,chekconnect;
sockaddr_in sockad;
sockad.sin_family = AF_INET;
sockad.sin_port   = htons(80);
sockad.sin_addr   = (in_addr)&inet_addr((const char*)&("127.0.0.1"));
WORD make=MAKEWORD(2,2);
WSAStartup(make,&data);
 
  sock = socket(AF_INET,SOCK_STREAM,0);
 
  if(sock==INVALID_SOCKET)
   {
      int msg = MessageBox(Handle,L"INVALID_SOCKET",L"Socket error",MB_OK|MB_RETRYCANCEL|MB_ICONERROR);
       switch(msg)
        {
            case ID_OK:
             break;
            case ID_RETRY:
             socket(AF_INET,SOCK_STREAM,0);
             break;
            case ID_CANCEL:
             break;
        }
   }
   else
   {
         bind = bind(sock,(sockaddr*)&sock,sizeof(sock));
         if(bind == SOCKET_ERROR)
          {
              int msgbinderror = MessageBox(Handle,L"SOCKET_ERROR",L"Bind error",MB_OK|MB_RETRYCANCEL|MB_ICONERROR);
               switch(msgbinderror)
                {
                    case ID_OK:
                     break;
                    case ID_RETRY:
                     bind(sock,(sockaddr*)&sock,sizeof(sock));
                     break;
                    case ID_CANCEL:
                     break;
                }
          }
       listen = listen(sock,SOMAXCONN);
         if(listen==SOCKET_ERROR)
          {
              int msglistenerror = MessageBox(Handle,L"SOCKET_ERROR",L"Listen error",MB_OK|MB_RETRYCANCEL|MB_ICONERROR);
               switch(msglistenerror)
                {
                    case ID_OK:
                     break;
                    case ID_RETRY:
                     listen(sock,SOMAXCONN);
                }
          }
   }
}
[BCC32 Error] Unit47.cpp(28): E2027 Must take address of a memory location
[BCC32 Error] Unit47.cpp(50): E2314 Call of nonfunction
[BCC32 Error] Unit47.cpp(59): E2314 Call of nonfunction
[BCC32 Error] Unit47.cpp(65): E2314 Call of nonfunction
[BCC32 Error] Unit47.cpp(74): E2314 Call of nonfunction
Проблемы у нег в bind -ом и с listen -ом..


Помогите кто сможет
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
21.02.2012, 05:39
Ответы с готовыми решениями:

калькулятор <-> 2 функции не работают универсально
Мне задали проект калькулятор как в windows или хотя бы похож. я сделал но у...

Две функции работают по отдельности, когда вместе выскакивает ошибка
Добрый день! Две функции работают по отдельности, когда вместе выскакивает...

Освобождение памяти после std:bind
Что имею: - CentOS - gcc 4.8 - valgrind Что делаю - С помощью...

[C] Обязателен ли вызов listen() после bind()?
Например,требуется реализовать клиент-сервер по протоколу TFTP. В случае...

Listen to me или listen me
Здравствуйте, почему первый вариант верный? В каких случаях я ставится to? Есть...

63
villu
203 / 204 / 16
Регистрация: 06.08.2011
Сообщений: 600
Записей в блоге: 1
22.02.2012, 12:00 #21
C++
1
saccept = accept(sock,(sockaddr*)&sockad,(int*)sizeof(&sockad));
ой как ужасно
во-первых не надо использовать ТОТ же sockad, если ты его не очистил. В вызове accept он работает как фильтр и следовательно система будет принимать соединения только от того, кто указан в этом адресе.
Создай новый, только пустой, либо не указывай его вообще.
C++
1
sockaddr_in accepted_addr = {0};
во-вторых
C++
1
(int*)sizeof(&sockad)
совсем не правильно. вызов требует указатель, на переменную из которой он сначала считает размер допустимой структуры, а потом запишет результат.
C++
1
2
3
int accepted_len = sizeof(accepted_addr);
// потом 
saccept = accept(sock,(sockaddr*)&accepted_addr, &accepted_len);
1
Programmer.
Прогер
631 / 262 / 15
Регистрация: 17.11.2010
Сообщений: 1,371
Записей в блоге: 2
22.02.2012, 13:49  [ТС] #22
villu,
Спасибо огромное за помош, сделано всё так, как вы сказалы, а тепер нажал на кнопочку и прога подвисла...
А как шас быть?

Ето значит что он ждет указание уже от клиента? или как ето понять, и вообше как я смогу определить есть ли контакт между серваком и клиентом? Смогу я послать хотя бы в Edit чтото?
0
villu
203 / 204 / 16
Регистрация: 06.08.2011
Сообщений: 600
Записей в блоге: 1
22.02.2012, 14:22 #23
Цитата Сообщение от Programmer. Посмотреть сообщение
villu,
А как шас быть?
Открываешь cmd

2 команды
netstat -ban
- покажет какие процессы на каких адресах висят
telnet 127.0.0.1 80
- подключится к твоему серверу. После подключения accept вернет управление.
1
Programmer.
Прогер
631 / 262 / 15
Регистрация: 17.11.2010
Сообщений: 1,371
Записей в блоге: 2
22.02.2012, 20:52  [ТС] #24
villu,
Сделал как сказалы, зависание тут же снилос, но выпало recv error (10057)
А в recv что не так?

Вот код:
C++
1
if((recv(sock,(char*)&buf,sizeof(buf),0))==SOCKET_ERROR)
0
villu
203 / 204 / 16
Регистрация: 06.08.2011
Сообщений: 600
Записей в блоге: 1
22.02.2012, 20:53 #25
Ну .. код давай )
0
Programmer.
Прогер
631 / 262 / 15
Регистрация: 17.11.2010
Сообщений: 1,371
Записей в блоге: 2
22.02.2012, 21:00  [ТС] #26
villu,
C++
1
2
3
4
5
6
7
8
9
10
11
12
 if((recv(sock,(char*)&buf,sizeof(buf),0))==SOCKET_ERROR)
                   {
                       int msgrcv = MessageBox(Handle,L"SOCKET_ERROR",L"recv erro",
                                               MB_RETRYCANCEL|MB_ICONERROR);
                           switch(msgrcv)
                            {
                                case ID_RETRY:
                                 ::recv(sock,(char*)&buf,sizeof(buf),0);
                                break;
                                case ID_CANCEL:
                                 break;
                            }
Вот, а описание переменных наверное уже на изусть изучили
0
villu
203 / 204 / 16
Регистрация: 06.08.2011
Сообщений: 600
Записей в блоге: 1
22.02.2012, 21:40 #27
C++
1
recv(saccepted,...,...,0)
тут должен быть сокет, который вернул accept
и что такое buf?
если коротко, то должно быть что-то типа
C++
1
2
3
4
5
std::vector<char> buf(1024); // например 
int recv = recv(saccepted, &buf[0], buf.size(),0);
// recved вернет количество считаннных байт, либо -1 
if (-1 != recved) buf.resize(recved);
else {//error}
Добавлено через 32 минуты
C++
1
2
int recved = recv(saccepted, &buf[0], buf.size(),0);
// recv вернет количество считаннных байт, либо -1
Конечно же...
1
Programmer.
Прогер
631 / 262 / 15
Регистрация: 17.11.2010
Сообщений: 1,371
Записей в блоге: 2
23.02.2012, 00:17  [ТС] #28
villu,
А без vector а нелзя ;(

просто: char buf[1024];

Cделал как сказал, но опять 10022

Не соовсем так но, вот посмотры вес код..
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
void __fastcall TForm47::Button1Click(TObject *Sender)
{
std::vector<char*>buf[1024];
WSADATA data;
time_t retrytime;
SOCKET sock,saccept;
int bind,listen,chekconnect,accs;
sockaddr_in sockad={0};
sockaddr_in sockadacc={0};
sockad.sin_family = AF_INET;
sockad.sin_port   = htons(80);
sockad.sin_addr.S_un.S_addr   = inet_addr("127.0.0.1");
WORD make=MAKEWORD(2,2);
WSAStartup(make,&data);
  sock = ::socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
 
if(sock==INVALID_SOCKET)
{
   ShowMessage(IntToStr(WSAGetLastError()));
      int msg = MessageBox(Handle,L"INVALID_SOCKET",L"Socket error",MB_RETRYCANCEL|MB_ICONERROR);
       switch(msg)
        {
            case ID_RETRY:
             ::socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
            break;
            case ID_CANCEL:
             break;
        }
 
}
 
   else
   {
         bind = ::bind(sock,(sockaddr*)&sockad,sizeof(sockad));
         if(bind == SOCKET_ERROR)
          {
              int msgbinderror = MessageBox(Handle,L"SOCKET_ERROR",L"Bind error",
                                            MB_RETRYCANCEL|MB_ICONERROR);
               switch(msgbinderror)
                {
                    case ID_RETRY:
                     ::bind(sock,(sockaddr*)&sockad,sizeof(sock));
                     break;
                    case ID_CANCEL:
                     break;
                }
          }
       listen = ::listen(sock,SOMAXCONN);
         if(listen==SOCKET_ERROR)
          {
              int msglistenerror = MessageBox(Handle,L"SOCKET_ERROR",L"Listen error",
                                              MB_RETRYCANCEL|MB_ICONERROR);
               switch(msglistenerror)
                {
                    case ID_RETRY:
                     ::listen(sock,SOMAXCONN);
                     break;
                    case ID_CANCEL:
                     break;
                }
          }
          else
          {
          accs = sizeof(sockadacc);
           saccept = accept(sock,(sockaddr*)&sockadacc,&accs);
            if(saccept==INVALID_SOCKET)
             {
                 int msgaccept = MessageBox(Handle,L"INVALID_SOCKET",L"accept error",
                                            MB_RETRYCANCEL|MB_ICONERROR);
                     switch(msgaccept)
                       {
                           case ID_RETRY:
                            Timer1->Enabled=true;
                            do
                               {
                                 ::accept(sock,(sockaddr*)&sockadacc,&accs);
                               } while(Timer1->Interval<5000);
                             break;
                           case ID_CANCEL:
                             break;
                       }
             }
             else
              {
                  if((recv(saccept,(char*)&buf[0],sizeof(buf),0))==SOCKET_ERROR)
                   {
                       int msgrcv = MessageBox(Handle,L"SOCKET_ERROR",L"recv erro",
                                               MB_RETRYCANCEL|MB_ICONERROR);
                           switch(msgrcv)
                            {
                                case ID_RETRY:
                                 ::recv(sock,(char*)&buf,sizeof(buf),0);
                                break;
                                case ID_CANCEL:
                                 break;
                            }
                   }
                   else if((send(sock,(char*)&buf,sizeof(buf),0))==SOCKET_ERROR)
                     {
                         int msgsend = MessageBox(Handle,L"SOCKET_ERROR",L"send error",
                                                  MB_RETRYCANCEL|MB_ICONERROR);
                            switch(msgsend)
                             {
                                 case ID_RETRY:
                                  ::send(sock,(char*)&buf,sizeof(buf),0);
                                  break;
                                 case ID_CANCEL:
                                  break;
                             }
                     }
              }
 
          }
          ShowMessage(IntToStr(WSAGetLastError()));
    }
  shutdown(sock,SD_BOTH);
  WSACleanup();
  closesocket(sock);
}
0
LK
Заблокирован
23.02.2012, 03:14 #29
Каха, забудь все это, прими саперави, и подумай.
1
Programmer.
Прогер
631 / 262 / 15
Регистрация: 17.11.2010
Сообщений: 1,371
Записей в блоге: 2
23.02.2012, 04:19  [ТС] #30
LK,
Цитата Сообщение от LK Посмотреть сообщение
Каха, забудь все это, прими саперави, и подумай.

Не по теме:

ЛК, друг мой, ой как мне хочется шас коняк, либо вино, или хотя бы пыво... но ктож тогда а коде будет думать а ? :D

0
LK
Заблокирован
23.02.2012, 04:49 #31
Каха, приезжай в Украину, и пофиг код - у нас такие девушки ))) .
1
Programmer.
Прогер
631 / 262 / 15
Регистрация: 17.11.2010
Сообщений: 1,371
Записей в блоге: 2
23.02.2012, 07:25  [ТС] #32
LK,

Ага девушки у вас супер(и не только )... я с отцом собирался но так и не собрался
0
LK
23.02.2012, 07:30
  #33

Не по теме:

Каха, нет, только девушки, и лучше без отца, а то никакой личной жизни :(

1
vxg
Модератор
3236 / 2040 / 319
Регистрация: 13.01.2012
Сообщений: 7,898
23.02.2012, 10:53 #34
не будет вот это работать никогда в жизни
C++
1
2
std::vector<char*>buf[1024];
::recv(sock,(char*)&buf,sizeof(buf),0);
потому как вам говорят а вы не слушаете. вам человек показал код где создавался вектор символов длиной 1024. в функцию передавался указатель на начало вектора и его размер полученный через вызов спец-функции объекта. вы же создали массив векторов (!) указателей (!) на символ, передали в функцию указатель на объект (!) и сказали функции что это буфер размером с размер объекта (!). у вас будет не то что ошибка - будет жесткое падение программы. читайте, нафига люди пишут? сравните для примера код который у вас получается с тем, что я вам чуть ли ни неделю назад выслал - один в один практически, вы просто не читаете. что то было бы не понятно - спросили, а так - ломитесь через лес затыкая компилятору рот первым что подвернулось под руку. простите, я не хочу вас обидеть и вообще - не наезжаю, просто как человек человеку говорю
1
villu
203 / 204 / 16
Регистрация: 06.08.2011
Сообщений: 600
Записей в блоге: 1
23.02.2012, 13:01 #35
Это все от непонимания основ.
кидаться писать сразу такой код, не понимая что, как и зачем, по-моему бессмысленно.
http://citforum.ru/book/cook/winsock.shtml вот, например, почитай. Там есть и пример эхо-сервера. Думаю поможет.

Ну и как vxg верно заметил, с самим с++ тоже проблемы.
1
Programmer.
Прогер
631 / 262 / 15
Регистрация: 17.11.2010
Сообщений: 1,371
Записей в блоге: 2
23.02.2012, 22:13  [ТС] #36
vxg,
Цитата Сообщение от vxg Посмотреть сообщение
::recv(sock,(char*)&buf,sizeof(buf),0);
ето я заменил етим
C++
1
int recved = recv(saccept,(char*)&buf[0],buf->size(),0);
(char*)&buf потому что сам он так не кастается(он же не соовсем чар)...

Но ошыбка та же...


villu,
Спосибо, почитаю шас


LK,

Не по теме:

Подумаю летом... :friends:



Добавлено через 17 минут
Не знпю за чем, но та ошибка сама сабой снелас, но шас последнее, send error (код 10057)

Вот код отправки:
C++
1
 if((send(sock,(char*)&buf,sizeof(buf),0))==SOCKET_ERROR)
П.С Читаю походу...
0
villu
203 / 204 / 16
Регистрация: 06.08.2011
Сообщений: 600
Записей в блоге: 1
23.02.2012, 22:16 #37
отправляешь не тем сокетом. Да и с буфером опять не то делаешь.
Читай доку ну а если еще больше хочешь про сеть, то книжку, например
http://www.internet-technologies.ru/books/book_103.html такую.
1
vxg
Модератор
3236 / 2040 / 319
Регистрация: 13.01.2012
Сообщений: 7,898
23.02.2012, 23:42 #38
путем нехитрых ковыряний в заголовочном файле winsock2.h обнаруживаем что коду ошибки соответствует WSAENOTCONN

Добавлено через 1 минуту
читая ман по send видим что она действительно может возвращать такой код и значит это что "The socket is not connected"
1
Programmer.
Прогер
631 / 262 / 15
Регистрация: 17.11.2010
Сообщений: 1,371
Записей в блоге: 2
24.02.2012, 08:36  [ТС] #39
vxg,
Цитата Сообщение от vxg Посмотреть сообщение
The socket is not connected"
А как он может стать connected ? уже не могу думать

Помогитье и с send ом ребята пожалуйста...

Добавлено через 2 минуты
Вот вес код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
void __fastcall TForm47::Button1Click(TObject *Sender)
{
std::vector<char*>buf[1024];
unsigned char bufsend[256] = "Hello world";
WSADATA data;
time_t retrytime;
SOCKET sock,saccept;
int bind,listen,chekconnect,accs;
sockaddr_in sockad={0};
sockaddr_in sockadacc={0};
sockad.sin_family = AF_INET;
sockad.sin_port   = htons(PORT);
sockad.sin_addr.S_un.S_addr   = inet_addr("127.0.0.1");
WORD make=MAKEWORD(2,2);
WSAStartup(make,&data);
  sock = ::socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
 
if(sock==INVALID_SOCKET)
  {
   ShowMessage(IntToStr(WSAGetLastError()));
          int msg = MessageBox(Handle,L"INVALID_SOCKET",L"Socket error",MB_RETRYCANCEL|MB_ICONERROR);
           switch(msg)
                {
                        case ID_RETRY:
                         ::socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
                        break;
                        case ID_CANCEL:
                         break;
                }
 
   }
 
   else
   {
                 bind = ::bind(sock,(sockaddr*)&sockad,sizeof(sockad));
                 if(bind == SOCKET_ERROR)
                  {
                          int msgbinderror = MessageBox(Handle,L"SOCKET_ERROR",L"Bind error",
                                                                                        MB_RETRYCANCEL|MB_ICONERROR);
                           switch(msgbinderror)
                                {
                                        case ID_RETRY:
                                         ::bind(sock,(sockaddr*)&sockad,sizeof(sock));
                                         break;
                                        case ID_CANCEL:
                                         break;
                                }
                  }
           listen = ::listen(sock,SOMAXCONN);
                 if(listen==SOCKET_ERROR)
                  {
                          int msglistenerror = MessageBox(Handle,L"SOCKET_ERROR",L"Listen error",
                                                                                          MB_RETRYCANCEL|MB_ICONERROR);
                           switch(msglistenerror)
                                {
                                        case ID_RETRY:
                                         ::listen(sock,SOMAXCONN);
                                         break;
                                        case ID_CANCEL:
                                         break;
                                }
                  }
                  else
                  {
                  accs = sizeof(sockadacc);
                   saccept = accept(sock,(sockaddr*)&sockadacc,&accs);
                        if(saccept==INVALID_SOCKET)
                         {
                                 int msgaccept = MessageBox(Handle,L"INVALID_SOCKET",L"accept error",
                                                                                        MB_RETRYCANCEL|MB_ICONERROR);
                                         switch(msgaccept)
                                           {
                                                   case ID_RETRY:
                                                        Timer1->Enabled=true;
                                                        do
                                                           {
                                                                 ::accept(sock,(sockaddr*)&sockadacc,&accs);
                                                           } while(Timer1->Interval<5000);
                                                         break;
                                                   case ID_CANCEL:
                                                         break;
                                           }
                         }
                         else
                          {
                           int recved = recv(saccept,(char*)&buf[0],buf->size(),0);
                                  if(recved == -1)
                                   {
                                           int msgrcv = MessageBox(Handle,L"SOCKET_ERROR",L"recv erro",
                                                                                           MB_RETRYCANCEL|MB_ICONERROR);
                                                   switch(msgrcv)
                                                        {
                                                                case ID_RETRY:
                                                                 ::recv(sock,(char*)&buf[0],buf->size(),0);
                                                                break;
                                                                case ID_CANCEL:
                                                                 break;
                                                        }
                                   }
                                  else
                                  {
                                      buf->resize(recved);
                                  }
                                   if((send(sock,(char*)&bufsend,sizeof(bufsend),0))==SOCKET_ERROR)
                                         {
                                                 int msgsend = MessageBox(Handle,L"SOCKET_ERROR",L"send error",
                                                                                 MB_RETRYCANCEL|MB_ICONERROR);
                                                      ShowMessage(IntToStr(WSAGetLastError()));
                                                        switch(msgsend)
                                                         {
                                                                 case ID_RETRY:
                                                                  ::send(sock,(char*)&bufsend,sizeof(bufsend),0);
                                                                  break;
                                                                 case ID_CANCEL:
                                                                  break;
                                                         }
                                         }
                          }
 
                  }
                  ShowMessage(IntToStr(WSAGetLastError()));
        }
  shutdown(sock,SD_BOTH);
  WSACleanup();
  closesocket(sock);
#undef PORT
}
0
vxg
Модератор
3236 / 2040 / 319
Регистрация: 13.01.2012
Сообщений: 7,898
24.02.2012, 09:31 #40
последовательность работы с сокетами в переводе на человеческий язык выглядит следующим образом:
для сервера
1. инициализируем библиотеку - ф-я WSAStartup
2. создаем сервер-сокет - ф-я socket
3. привязываем сервер-сокет к определенному адаптеру (по его IP) или всем адаптерам (если IP равен "0" или в качестве адреса указано INADDR_ANY) - ф-я bind
4. ставим сервер-сокет на прослушивание - ф-я listen
5. принимаем подключения от клиентов - ф-я accept - получаемый при этом клиент-сокет используется для общения с клиентами
6. принимаем / шлем данные через клиент-сокет - ф-ии recv / send
7. закрываем клиент-сокет когда он отключился (recv принял ноль байт), при ошибках (если ваша задача предполагает такой способ взаимодействия), принудительно (например, по желанию администратора сервера) или как-либо еще - ф-я closesocket
8. закрываем сервер-сокет когда сервер прекращает свое существование - ф-я closesocket
9. завершаем работу с библиотекой - ф-я WSACleanup
====
вы пересылаете данные через клиент-сокет, а принимаете по-прежнему через сервер-сокет, а такого быть не должно - сервер-сокет так не используется, он нужен только для приема подключений от клиентов
2
24.02.2012, 09:31
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
24.02.2012, 09:31

Перегруженные функции и bind
Привет всем! В классе QPushButton есть две версии функции 1....

Адаптер функции bind()
Читаю у Липпмана про адаптер bind, ...какие-то знакоместа. Компилятор на них...

Ошибка после функции bind
Пытаюсь первый раз написать по книге клиент-сервер. В этом практически ничего...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru