Форум Херсона. Форум Херсонской молодежи.

Форум Херсона. Форум Херсонской молодежи. (http://forum.norma4.net.ua/)
-   Программирование (http://forum.norma4.net.ua/programmirovanie/)
-   -   Нужна помощь в освоении программирования (http://forum.norma4.net.ua/programmirovanie/73828-nuzhna-pomoshue-v-osvoenii-programmirovaniya.html)

ПВО 13.10.2014 19:38

Нужна помощь в освоении программирования
 

Мне нужно написать программу под виндовс. Программа должна работать через интернет и связывать компьютеры пользователей напрямую. Какой язык выбрать?

У меня сейчас стоит визуал студио 2008. Книжек, по которым можно быстро освоиться не нашел. Давно раньше программировал на паскале и с++.

Lester 13.10.2014 20:37

> Какой язык выбрать?

Какой лучше знаешь ты, либо твой хороший знакомый, которому не лень будет помогать. В этом деле программистов лучше не слушать - они будут хвалить свой любимый язык, а для этой задачи подойдет чуть ли не любой популярный.

> Давно раньше программировал на паскале и с++.

C++ сложный язык и очень сильно эволюционировал в последнее время (став намного удобнее и при том еще сложнее). Если использовать его - то лучше в паре с удобным и простым фреймворком, например, Qt (там есть примеры fortune server и fortune client). Заодно код можно будет собрать хоть под Android, хоть под iOS, хоть под Linux. Плюс в Qt есть практически все. Про паскаль не скажу, в современном виде это, наверное, только Delphi. Тут есть для него пример:

http://rosettacode.org/wiki/Echo_server#Delphi


П.С. хотя вспомнил - есть еще Free Pascal и Lazarus, открытый аналог Delphi

osp 30.10.2014 19:19

советую Делфи, если пишешь на паскале
или сразу учи Java, так как программа на джаве запустится на любом устройстве и в любой системе

PhoeniXX 30.10.2014 19:21

Цитата:

Сообщение от osp (Сообщение 1151367)
сразу учи Java, так как программа на джаве запустится на любом устройстве и в любой системе

А разве C++, .Net, python, ruby, node.js запустится не на любой OS? не надоели стереотипы?

osp 30.10.2014 19:42

Цитата:

Сообщение от PhoeniXX (Сообщение 1151368)
А разве C++, .Net, python, ruby, node.js запустится не на любой OS? не надоели стереотипы?

Думаю, для начала, новичку проще начать все-таки с Джава

С++ и другие... это тоже пальто, но на выворот

Почесав затылок, юзер дописал через 4 минуты
Цитата:

Сообщение от ПВО (Сообщение 1147380)
Мне нужно написать программу под виндовс. Программа должна работать через интернет и связывать компьютеры пользователей напрямую. Какой язык выбрать?

У меня сейчас стоит визуал студио 2008. Книжек, по которым можно быстро освоиться не нашел. Давно раньше программировал на паскале и с++.

Вы, лучше напишите конкретно в чем суть программы... и станет ясно на чем писать.

А спорить, кто круче С++ или Java можно долго...
Если человек выучил Джаву, он смело выучит любой другой язык (они все похожи)

Lester 30.10.2014 20:15

Цитата:

Сообщение от osp (Сообщение 1151367)
или сразу учи Java, так как программа на джаве запустится на любом устройстве и в любой системе

Это не так, в реальности Java может либо вообще не поддерживаться (Minix), иметь куцую и нестабильную реализацию (Haiku, Hurd), и даже вообще запрещена (iOS). Кроме того, различные устройства и системы не просто так различные, как и API к ним, и какой-нибудь Eclipse, например, хрен запустится на планшете с Android, ровно как и наоборот (хотя и есть извращения, как с NaCl в ChromeOS, например).

Цитата:

Сообщение от osp (Сообщение 1151372)
С++ и другие... это тоже пальто, но на выворот

Ага, а парадигмы программирования, семантика, синтаксис, модель управления памятью, типизация и т.д. и т.п. - это все нудная и заумная фигня, все равно все одинаковое.

kovalev 07.11.2014 03:17

пиши на том, что знает твой сосед ) ну или знакомый.Если задание разовое и для себя. Если в будущем для денег - то стат. анализ зарплат предполагаемого региона, в котором будешь работать )

ПВО 10.11.2014 17:58

Спасибо за советы, пока остановился на c# просто потому, что попалась книга, которая позволила начать осваиваться на визуал студио 2008.

В программе должно быть: проводник, просмотр картинок, базы данных, которые должны синхронизироваться по сети с другими компьютерами напрямую.

Сейчас вопрос по проводнику. Есть два окошка - дерево каталогов и список файлов. Насколько я понимаю, в тулбоксе нет таких готовых инструментов. Нашел в сети ДЛЛ-ки, которые выполняют такие функции и подключил их к моей программе. Это такой путь - искать готовые коды и ДЛЛ-ки и использовать их, чтобы самому глубоко не кодировать? Какой ресурс предлагает базы таких готовых решений?

PhoeniXX 10.11.2014 18:46

Цитата:

Сообщение от ПВО (Сообщение 1154103)
Спасибо за советы, пока остановился на c# просто потому, что попалась книга, которая позволила начать осваиваться на визуал студио 2008.

В программе должно быть: проводник, просмотр картинок, базы данных, которые должны синхронизироваться по сети с другими компьютерами напрямую.

Сейчас вопрос по проводнику. Есть два окошка - дерево каталогов и список файлов. Насколько я понимаю, в тулбоксе нет таких готовых инструментов. Нашел в сети ДЛЛ-ки, которые выполняют такие функции и подключил их к моей программе. Это такой путь - искать готовые коды и ДЛЛ-ки и использовать их, чтобы самому глубоко не кодировать? Какой ресурс предлагает базы таких готовых решений?

Не всегда хорошо искать отдельное решение, написаное кем-то, так как тогда со временем проект обрастёться тоннами не понятно чего, и так же очень часто, если тебе нужно будет изменить функциональность, не каждая найденная библиотека позволяет это сделать.

В тулбоксе нет готового контрола, но там есть TreeView и так же есть
ListView, который умеет отображать данные в табличном\плитковом представлении.

Есть еще часто мелькающее решение по использованию WebBrowser, которому указываеться путь на файловой системе, и он использую стандартный ActiveX - отображает тот же проводник, но как по мне правильнее написать самому, учитывая что там кода как-то и не сильно много. Строк 30-60 для обычного простого проводника

ПВО 05.01.2015 21:43

Неделю ковыряю cs а он меня уже вконец выбесил :) У кого как было - привыкаешь и просто перестаешь беситься или все-таки можно разобраться и что-то нормально сделать?

Итак, задача. Перевод компьютера в спящий режим.

Ставлю чекбокс, при отметке которого запускается таймер. При срабатывании таймера нужно открыть окошко с предупреждением о переводе в спящий режим. Пробовал MessageBox, но он не показывается поверх всех окон. Пробовал вторую форму открывать, но не могу оттуда передать параметр в первую, что вторую закрыл пользователь. Пробовал notifyIcon1.ShowBalloonTip, но тоже - и не показывается поверх кино и не срабатывает NotifyIcon1_BalloonTipClicked.

А еще, когда форма не видна на экране, перестает работать таймер. :cray:

PhoeniXX 05.01.2015 22:41

Цитата:

Сообщение от ПВО (Сообщение 1170001)
Ставлю чекбокс, при отметке которого запускается таймер. При срабатывании таймера нужно открыть окошко с предупреждением о переводе в спящий режим. Пробовал MessageBox, но он не показывается поверх всех окон.

Ну да, это ж модальное окно. А оно и должно быть открыто поверх текущего окна, которое его открыло.
Цитата:

Сообщение от ПВО (Сообщение 1170001)
Пробовал вторую форму открывать, но не могу оттуда передать параметр в первую, что вторую закрыл пользователь.

Типа такого должно работать:

Код:

MyPopupForm form = new MyPopupForm();
form.Closing += form_Closing; // оно будет вызвано когда форма будет закрываться
form.Show();

private void form_Closing(object sender, CancelEventArgs e)
{
    MyPopupForm form = (MyPopupForm) sender;
    string myParameter = form.MyCustomParameter; // это свойство новой формы, в которую можно сохранить нужный параметр
    // ну и дальше его можно использовать
}

Цитата:

Сообщение от ПВО (Сообщение 1170001)
А еще, когда форма не видна на экране, перестает работать таймер. :cray:

Таймер должен работать не зависимо от видимости окошка. Если только окно не было закрыто.

А вообще, если есть вопросы, то нужно и код какой-то показывать, так как отвечать на вопросы без кода это как гадание на кофейной гуще.

ПВО 09.01.2015 18:36

Попытка открыть вторую форму Form2
Код:

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace forvard
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        Form2 f2 = new Form2();
        f2.Closing += form2_Closing; // оно будет вызвано когда форма будет закрываться
        f2.Show();

        private void f2_Closing(object sender, CancelEventArgs e)
        {
        }
    }
}

Выдает ошибку:
Цитата:

Invalid token '+=' in class, struct, or interface member declaration
У меня визуал студио 2008.

PhoeniXX 09.01.2015 19:58

Цитата:

Сообщение от ПВО (Сообщение 1171067)
Попытка открыть вторую форму Form2
Код:

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace forvard
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        Form2 f2 = new Form2();
        f2.Closing += form2_Closing; // оно будет вызвано когда форма будет закрываться
        f2.Show();

        private void f2_Closing(object sender, CancelEventArgs e)
        {
        }
    }
}

Выдает ошибку:

У меня визуал студио 2008.

Ну да. Код должен находится внутри метода, а тут идёт описание класа, в нём два метода, и кусок кода который относится непонятно к чему, и не понятно когда он должен вызываться.

Потом метод снизу называется f2_Closing, а в подписывании указано:
f2.Closing += form2_Closing; . Метод должен же быть одним и тем же. А так описан метод f2_Closing, а попытка использования form2_Closing, которого тут нету.

Должно быть хотя бы где-то так, хотя в данном случае форма будет открываться при запуске основной формы:

Код:

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace forvard
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            Form2 f2 = new Form2();
            f2.Closing += f2_Closing; // оно будет вызвано когда форма будет закрываться
            f2.Show();
        }

        private void f2_Closing(object sender, CancelEventArgs e)
        {
        }
    }
}


ПВО 09.01.2015 20:19

вот так работает:
Код:

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace forvard
{
    public partial class Form1 : Form
    {
        Form2 f2;
        public Form1()
        {
            InitializeComponent();
            f2 = new Form2();
            f2.FormClosing += delegate { f2_Closing(); };
        }

        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            f2.ShowDialog();

        }
        void f2_Closing()
        {
            MessageBox.Show("For2 is closing now!");
        }
    }
}

пока это устраивает, буду на этой основе дальше кодить.

Почесав затылок, юзер дописал через 8 минут
Цитата:

Сообщение от PhoeniXX (Сообщение 1171089)
Код должен находится внутри метода, а тут идёт описание класа, в нём два метода, и кусок кода который относится непонятно к чему, и не понятно когда он должен вызываться.

ну вот, теперь в голове все сложилось - классы и методы :)

ПВО 29.04.2015 02:39

Есть такая задача... нужно в не используемую оперативную память записывать нужный код и оставлять это свободным для использования. Другими словами, определяем место в озу, которое не испол.дается в данный момент, его заполняем кодом, и оставляем к нему доступ других программ, то есть, не используемая память должна содержать определенный код

Интересует вопрос - можно ли такое в принципе сделать? Насколько это сложно или сколько это может стоить?

Я пробовал на си шарп что то делать, - смотрел размер свободной паияти, записывал в большую матрицу данные, и смотрел опять размер свободной памяти, но она как была свободной, так и оставалась. К тому же медленно все происходило.

Lester 29.04.2015 04:19

Цитата:

Сообщение от ПВО (Сообщение 1203119)
Есть такая задача... нужно в не используемую оперативную память записывать нужный код и оставлять это свободным для использования. Другими словами, определяем место в озу, которое не испол.дается в данный момент, его заполняем кодом, и оставляем к нему доступ других программ, то есть, не используемая память должна содержать определенный код

Интересует вопрос - можно ли такое в принципе сделать? Насколько это сложно или сколько это может стоить?

Я пробовал на си шарп что то делать, - смотрел размер свободной паияти, записывал в большую матрицу данные, и смотрел опять размер свободной памяти, но она как была свободной, так и оставалась. К тому же медленно все происходило.


"оставляем к нему доступ других программ" - очевидно речь идет о shared memory. Вот дока для C#:

https://msdn.microsoft.com/ru-ru/lib...vs.110%29.aspx

"определяем место в озу, которое не испол.дается в данный момент, его заполняем кодом" - типичное поведение ОС для файлового кэша. А эффективно реализовать такое же на уровне процесса в user space не получится. Так что просто пишем сколько нужно, а ОС разрулит. Это если речь не идет о регулярной передаче и обновлении гигабайт данных, тогда задача изначально решается неверно.

"и смотрел опять размер свободной памяти, но она как была свободной, так и оставалась" - значит рантайм C# изначально запросил достаточно памяти для размещения новых данных. Это делается для оптимизации. Даже банальный malloc большей частью занимается просто "нарезанием", а не вызовом syscall mmap на каждый чих. Ну или смотреть использование памяти было надо не там.

wouldnt_even 29.04.2015 04:58

Цитата:

Сообщение от Lester (Сообщение 1203120)
"и смотрел опять размер свободной памяти, но она как была свободной, так и оставалась" - значит рантайм C# изначально запросил достаточно памяти для размещения новых данных. Это делается для оптимизации. Даже банальный malloc большей частью занимается просто "нарезанием", а не вызовом syscall mmap на каждый чих. Ну или смотреть использование памяти было надо не там.

я могу ошибаться, но это вполне может быть результат работы garbage collector'a. то есть объекты, к которым нет обращения, уничтожаются. я допускаю, что если создан огромный массив, к торому потом нет никакого референса, довольно быстро уничтожается. а долго это могло происходить, если массив больше свободной памяти, поэтому задействовался своп.

Lester 29.04.2015 12:02

Цитата:

Сообщение от wouldnt_even (Сообщение 1203121)
я могу ошибаться, но это вполне может быть результат работы garbage collector'a. то есть объекты, к которым нет обращения, уничтожаются. я допускаю, что если создан огромный массив, к торому потом нет никакого референса, довольно быстро уничтожается. а долго это могло происходить, если массив больше свободной памяти, поэтому задействовался своп.

Я по описанию предположил, что он смотрел прямо в процессе работы, а значит GC не должен был еще отработать. И если память оставалась свободной - до сильного свопинга дойти было не должно, кроме того значит реально много памяти и не нужно было. Хотя да, это я начал гадать, тут надо все спрашивать у автора - сколько памяти процесс использовал, как и когда он смотрел, реально ли матрица большая, как именно она заполнялась и пр.

PhoeniXX 29.04.2015 12:17

Цитата:

Сообщение от ПВО (Сообщение 1203119)
Я пробовал на си шарп что то делать, - смотрел размер свободной паияти, записывал в большую матрицу данные, и смотрел опять размер свободной памяти, но она как была свободной, так и оставалась. К тому же медленно все происходило.

Простой пример:

Код:

                       
const int count = 1024*1024*1024/sizeof(int);
Console.ReadLine();
int[] q = new int[count];

//for (int index = 0; index < q.Length; index++)
//{
//        q[index] = 0;
//}
Console.ReadLine();

Но тут есть момент, если код ниже так и останется закоментированным, то компилятор вырежет не используемые переменную, и память использована не будет. Если его раскомментировать, но даже не выполнять заполнение массива, тогда он заалокейтит 1гб памяти. Но это Private memory, а не Shared.

GC может вполне и в процессе работы метода вмешаться и удалить не используемые данные. Только опять же это будет private память, и она будет доступна только этому процессу.

В чем практическая ценность задачи? Зачем нужна такая логика?

Lester 29.04.2015 13:06

Цитата:

Сообщение от PhoeniXX (Сообщение 1203178)
Если его раскомментировать, но даже не выполнять заполнение массива, тогда он заалокейтит 1гб памяти.

Значит компилятор C# не умеет в оптимизацию, т.к. такое тоже можно выкидывать :)

PHP код:

~$ cat ./test.cpp 
#include <vector>

int main()
{
    
std::vector<intv1024 1024 1024 );
    for( 
int)
        
0;
}
~$ 
clang++-libc++ -std=c++11 -Ofast -./test.cpp 
~$ cat ./test.s
    
.text
    
.file    "./test.cpp"
    
.globl    main
    
.align    160x90
    
.type    main,@function
main:                                   # @main
    
.cfi_startproc
# BB#0:
    
xorl    %eax, %eax
    retq
.Lfunc_end0:
    .
size    main, .Lfunc_end0-main
    
.cfi_endproc


    
.ident    "Ubuntu clang version 3.7.0-svn235834-1~exp1 (trunk) (based on LLVM 3.7.0)"
    
.section    ".note.GNU-stack","",@progbits 

Впрочем у него "медленно все происходило", а значит таки что-то делалось. В общем нужен код.

ПВО 30.04.2015 17:55

Вложений: 1
Ребята, вы точно наши, а не из гарварда пишите? :)

Привожу код, а в комментарии еще буду вникать.

В целом так:

1. Определяем размер свободной части ОЗУ
2. Высчитываем, сколько туда поместится строк текста
3. Если процессор не загружен, записываем в переменную строку


Код:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;

namespace mg
{
    public partial class Form1 : Form
    {
        PerformanceCounter ramCounter = new PerformanceCounter("Memory", "Available MBytes");
        PerformanceCounter cpuCounter = new PerformanceCounter();
        int cpucnt;
        string[] stringArray;
        string str;
        int arrlenght;
        int ramfree;
        int i = 1;

        public Form1()
        {
            InitializeComponent();
            cpuCounter.CategoryName = "Processor";
            cpuCounter.CounterName = "% Processor Time";
            cpuCounter.InstanceName = "_Total";
            str = textBox1.Text;
            ramfree = (int)ramCounter.NextValue();
            label_memory.Text = ramfree+"MB";
        }

        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBox1.Checked) timer1.Enabled = true; else timer1.Enabled = false;
            textBox1.Text = str;
        }

        private void timer1_Tick(object sender, EventArgs e) // Каждые 10 милисекунд дописываем строку в память
        {
            cpucnt = (int)cpuCounter.NextValue(); // Определяем загрузку процессора
            if (cpucnt < 35)
            {
                arrlenght = (int)ramfree*1024*1024 / (textBox1.Text.Length*2+10); // Определяем - сколько в памяти поместится нужных строк
                arrlenght = (int)arrlenght / 10;
//                stringArray = new string[arrlenght];
                label_arr.Text = "Допуст. кол. в массиве: " + arrlenght.ToString();
                label_txt_nb.Text = textBox1.Text.Length.ToString();

                if ( i+100 < arrlenght )
                {
//                  stringArray[i - 1] = textBox1.Text; // Сначала я записывал строку в массив
                    for (int n = 0; n < 100; n++) { str = str + textBox1.Text; } // Потом дописывал строку в переменную стринг
                    i = i + 100;
                }

//                stringArray = null;
             
                if (i >= arrlenght) { i = 1;  str = null; }
            }
        }

        private void timer_renew_Tick(object sender, EventArgs e) // Каждую секунду обновляем показания на форме
        {
                label_cpu.Text = cpucnt + "%";
                    label_i.Text = "i = " + i;
                ramfree = (int)ramCounter.NextValue();
                label_free_2.Text = ramfree+"MB";

        }
    }
}


PhoeniXX 30.04.2015 18:07

Цитата:

Сообщение от ПВО (Сообщение 1203585)

Код:

                if ( i+100 < arrlenght )
                {
//                  stringArray[i - 1] = textBox1.Text; // Сначала я записывал строку в массив
                    for (int n = 0; n < 100; n++) { str = str + textBox1.Text; } // Потом дописывал строку в переменную стринг
                    i = i + 100;
                }


Так как в массив строк stringArray сохраняется тот же экземпляр строки, то новую память он не использует, а просто создаёт новые ссылки на ту же строку. И как следствие испольуземые память растёт очень медленно - по 4\8 байт за проход.

Во втором случае с str = str + textBox1.Text - да, тут память используется активнее, но так как промежуточные состояния переменной str нигде не сохраняются, то и они очень быстро уничтожаются GC в процессе работы метода.

При данном подходе компромиссом будет где-то такое внутри цикла, который будет выполнять этот кусок для каждого элемента массива:

Код:

str = str + textBox1.Text;
stringArray[i - 1] = str;

Ну и плюс, если нужно занимать определённое кол-во памяти, тогда вместо textBox1.Text должно быть значение в коде, чтобы можно было посчитать размер памяти используемый в процессе.

Опять же, это private память, а не shared, и таким образом процесс просто будет забирать свободную память у системы(наверняка файловый кэш), и все остальные процессы начнут активно свапиться, и как следствие все приложения начнут тупить.

Школьник 30.04.2015 18:09


Lester 30.04.2015 18:15

Цитата:

Сообщение от PhoeniXX (Сообщение 1203591)
Опять же, это private память, а не shared, и таким образом процесс просто будет забирать свободную память у системы(наверняка файловый кэш), и все остальные процессы начнут активно свапиться, и как следствие все приложения начнут тупить.

И потому очень интересно - а что за задача вообще будет решаться таким способом. Возможно подойдет банальная СУБД с shared cache, например, berkeley db или sqlite.

ПВО 30.04.2015 22:46

На сейчас задача такая - забить не используемую область озу нужным кодом и оставить ее в свободном доступе.: По идее, тут самое место что то типа прямому доступу к памяти, просто я когда искал инфу, то ничего нужного не нашел. Мой код, это просто попытка выкрутиться.

wouldnt_even 01.05.2015 09:02

"забить нужным кодом" - чушь какая-то. без оглядки на размер памяти? объем кода? просто забить? что надо доказать шефу, что на компе мало памяти и нужен апгрейд? или неуклюжая попытка написать вирус? :)

ПВО 30.05.2015 14:52

wouldnt_even, ну, все тривиальные задачи давно уже решены. Остается ходить по неведомым дорожкам :)

ПВО 16.10.2016 13:29

Новая задача.

Нужно, чтобы один компьютер напрямую соединялся с другим компьютером в интернете и передавал данные. Для этого компьютер, который вышел в сеть, должен оставлять свои идентификационные данные (или как они называются?) на сайте в сети. А другой компьютер мог брать эти данные и напрямую связываться с первым компьютером.

Что-то вроде связи торрент-трекеров.

Сколько ни ищу информации по форумам и книжкам - как это можно сделать, какие принципы, какие методы или функции есть для этого в языках программирования, но ничего пока не нашел, чтобы можно было уяснить подробно.

Может кто подскажет - где искать ответы?

olegjack 16.10.2016 14:46

Как то совсем непонятно что нужно. Выделенный IP, PPTP поднять или сервисы типа dyndns, noip.
Чем старые добрые почтовые и фтп протоколы неподходят?

ПВО 16.10.2016 15:22

Я сам не знаю - как это называется. Мне нужно, чтобы программа на одном компьютере связывалась напрямую с такой же программой на другом компьютере в сети. Каждый комп в сети должен иметь свой уникальный адрес, чтобы к нему можно было обращаться. Что это за адресация, какие есть процедуры в языках программирования для реализации таких возможностей?


Время на сервере: 16:45.

vBulletin 3, Copyright © 2000-2017, Jelsoft Enterprises Ltd.
Русский перевод: zCarot, Vovan & Co