26

Re: Программирование. Как сделать сервер дома?

Mars пишет:

Не пойму по какому принципу  удерживается соединение - как вообще определяется открыто соединение или закрыто.

сделайте таймер - если данных нет 11 минут (10 минут на стоянках интервал)  рвите соединение.

27

Re: Программирование. Как сделать сервер дома?

я про таймер думаю. Но неужели нет программного определения установлено соединение или разорвано для TCP соединения?
если по каким-то причинам, допустим проеду в зоне помех, то соединение будет восстановлено аж через 10 мин. На мотоцикле 15 минут в любую точку киева можно телепортировать big_smile . Как то не очень.. такой обрыв.

Отредактировано Mars (27-02-2012 20:13:21)

28

Re: Программирование. Как сделать сервер дома?

Не, если данные передаются - коннект не рвать.

29

Re: Программирование. Как сделать сервер дома?

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

30

Re: Программирование. Как сделать сервер дома?

Ну вы можете попробовать с определенным интервалом отправлять посылку какую нибудь и если в момент передачи возникает ошибка собственно можно её перехватить и закрыть соединение.

31

Re: Программирование. Как сделать сервер дома?

всюду пишут что закрытие только по истечению времени. я так понял что невозможно определить кокда клиент отваливается, ведь он абсолютно ничего не передает. Похоже нужно делать асинхронный много поточный сервер. После обрыва соединения прибор снова выйдет на связь и программа должна воспринять его как второго клиента. А первый поток(или сокет как там его) закрыть по истечению 10.. 15 минут.

32

Re: Программирование. Как сделать сервер дома?

как вообще определяется открыто соединение или закрыто

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

а вообще полезно изучить матчасть smile

Все, что нельзя написать на ассемблере, можно доделать паяльником (ц)

33

Re: Программирование. Как сделать сервер дома?

Все сейчас переделываю как вы пишете. Суть понимаю. Но к устройству я доступа не имею. При создании чатов так и делают. Перед отключением делают принудительную посылку ключевое слово вроде "Дисконект". Но я прошивку прибора не могу переделать. И обрыв связи может быть внезапным, будь до помехи или просто коротнуло..
Нашел другой пример многопоточного сервера, сейчас разбираюсь. Уже работает. После рестарта сообщает о новом соединении (правда предыдущий поток не закрывает, не знаю чем это чревато.. где-то поток висит ну и ладно..).
вот с этой странички пример взял http://www.cyberforum.ru/csharp-net/thread225508.html - правлю под себя.

34

Re: Программирование. Как сделать сервер дома?

Mars пишет:

предыдущий поток не закрывает, не знаю чем это чревато.. где-то поток висит ну и ладно

чревато достичь лимита соединений, т.к. по-умолчанию таймаут для сокета вроде большой очень.
Бегло глянул на пример - там в принципе все что надо есть: и очереди и список коннектов. Остается только немного допилить под себя парсер принятого пакета и сохранение данных куда-то..

Все, что нельзя написать на ассемблере, можно доделать паяльником (ц)

35

Re: Программирование. Как сделать сервер дома?

alexdob пишет:

Вечером постараюсь выложить пример реализации второго варианта

извиняюсь, "вечер" слишком растянулся в связи в большими событиями в моей маленькой жизни.. обещаю вернуться к вам после 5го числа.. smile всем успехов во всех начинаниях..

http://www.djbdb.net/userbar/married.png

Отредактировано alexdob (01-03-2012 22:42:17)

Все, что нельзя написать на ассемблере, можно доделать паяльником (ц)

36

Re: Программирование. Как сделать сервер дома?

alexdob пишет:
alexdob пишет:

Вечером постараюсь выложить пример реализации второго варианта

извиняюсь, "вечер" слишком растянулся в связи в большими событиями в моей маленькой жизни.. обещаю вернуться к вам после 5го числа.. smile всем успехов во всех начинаниях..

http://www.djbdb.net/userbar/married.png

Ахтыж ё! Поздравления))

37

Re: Программирование. Как сделать сервер дома?

Мои тоже поздравлениия! стачстивого месяца  smile

38

Re: Программирование. Как сделать сервер дома?

http://www.djbdb.net/userbar/married.png

Оооооо!!!! Это событие!!! Примите поздравления  smile

39

Re: Программирование. Как сделать сервер дома?

Такие вещи лучше делать на ком-то из линуксов.
Например, берём Ubuntu Server. В комплекте уже будет бд, веб-сервер, и всё что угодно, надо будет только настроить.

Принимаем на линуксе данные с устройства одной командой.
nc -l 50666, где 50666 - номер порта, на который идут данные с устройства.

или например принимаем данные, пишем их в файл, и сразу же передаём дальше на gps-tracker.com.ua

nc -l 50001 | tee gps.log > nc 46.4.18.67 10015
смотрим файл в "онлайне"
tail -f gps.log

Делаем лучше. Устанавливаем демон tcp-соединений xinetd
прописываем в его конфиг информацию о нашем gps-oko-слушающем сервисе, что-то потипу такого

disable=no
id=gps_oko
type=unlisted
socket_type=stream
protocol=tcp
port=50666
log_type= FILE /var/log/gps/gps_oko.log
server=/usr/local/gps_in_oko.py

/usr/local/gps_in_oko.py - программа, на вход которой будут идти данные с устройств. Для каждой новой сессии/нового устройства будет вызываться новый экземпляр программы. И никакой возни со всякими tcp. Что-то подобное, смею предположить, сделано и тут.

40

Re: Программирование. Как сделать сервер дома?

Очень интересный материал спасибо. Теперь я пожалуй тоже чего-нибудь смастерю.

41

Re: Программирование. Как сделать сервер дома?

Hi people.. i'm here
Вот лето пролетело и настала осень.. стало как-то грустно на душе, да и тема чего-то притихла..
вот в связи с идейным кризисом (и задолбавшим мозг ремонтом в новой квартире) решил немного отвлечься от "бытовухи", установить визуалку и посмотреть чего интересного народ написал за последние пол года.. а тут - тишина sad может уже никому не интересна данная тема?

Отредактировано alexdob (03-09-2012 21:56:18)

Все, что нельзя написать на ассемблере, можно доделать паяльником (ц)

42

Re: Программирование. Как сделать сервер дома?

Наверное все все сделали и разобрались)

43

Re: Программирование. Как сделать сервер дома?

Меня все не покидает идея релизовать хотябы одноюзерный прием данных на свой комп. Но на чем я остановился. Во  первых C# у меня был пробный и он спуся вроде 3 нед отлючился. Как раз написал парсер многопоточный.
Поскольку я запнулся не на нем, а на том как реализовать вывод без перезагрузки, перекинулся на уроки по HTML.. CSS.. потом javascrip и PHp. Каждый день по миллиметру двигаюсь. Просто создаю какие-то сайты примитивные.
Основу - каким образом делается все без перезагрузки изучил. И сейчас можно дальше продвигаться в принципе, но никак. Пока подошел к базам данных, уже пора использовать нормально не текстовый файл а базу данных.

И все у меня медленно, бо на форумах программистов мало толку спрашивать. Никто не отвечает или говорят гугль в помощь.. таке.

Надо бы опять С# найти или ломаный, или какуюто бесплатную ограниченную версию. И подключаться с выводом в страничку браузера. Я ж не программер... не мой хлеб. И знакомых даже спросить не у кого. Позади поезда бегу вопщем.  neutral

44

Re: Программирование. Как сделать сервер дома?

Лично я скачал 2010 экспресс студию с оф.сайта, зарегистрировал ее там же и пользуюсь smile (как вариант тянуть с рутрекера гигабайты:) )

Можно попробовать разобраться и в вашей трудности (заодно обменяться опытом, а может и команда gps-tracker чего подскажет)

Все, что нельзя написать на ассемблере, можно доделать паяльником (ц)

45

Re: Программирование. Как сделать сервер дома?

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

И так.. будем считать, что студию скачали, парсер для своего девайса написан и рвется в бой smile
для того, что бы сохранять данные в базу потребуется библиотека-провайдер. Я буду приводить примеры на MySQL, т.к. с ней работал больше-чаще-толще, а за PostgreSQL не брался уже лет 5 (многое наверное изменилось)
Идем на http://www.mysql.com/downloads/connector/net/ выбираем нужную версию и качаем (нам потребуется только mysql.data.dll - ее то и импортируем в проект)

using MySql.Data.MySqlClient;

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

CREATE TABLE `raw_data` (
    `dev_id` TINYINT UNSIGNED NOT NULL DEFAULT '0',
    `raw_data` VARBINARY(23) NOT NULL,
    `data_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB;

TINYINT - т.к. девайсов не много и их идентификатор берется из внешней таблицы (здесь не показано)

в программе определим структуру "сырой точки":

internal class struct_raw_point
{
    internal int dev_id = 1;
    internal byte[] raw_data;
}

(ох уж эта "техника дошла" - классы и структуры имеют небольшие отличия - по привычке обозвал классом, зато с понятным именем smile )

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

    internal static class mod_db
    {
        private static MySqlCommand cmd;
        private static MySqlConnection conn;
        private static MySqlDataReader dr;

        private const string mod_name   = "mod_db";
        private const string DB_NAME    = "gpssrv";
        private const string DB_HOST    = "localhost";
        private const string DB_USER    = "GPSsrv";
        private const string DB_PASSWD  = "D8pO1uxA";

        private const int ITERATION_INTERVAL = 10000;

        private static readonly List<struct_raw_point> queue_glob = new List<struct_raw_point>();
        private static readonly List<struct_raw_point> queue_loc  = new List<struct_raw_point>();

        private static readonly Thread worker = new Thread(new ThreadStart(main));

        static mod_db()
        {
            init_db_conn(ref conn, ref cmd, ref dr);
            worker.Start();
        }
...
}

собственно этого кода целиком и полностью достаточно (за исключением основного обработчика main), что бы проинициализировать подключение к базе и запустить новую "нить".

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

internal static void init_db_conn(ref MySqlConnection conn, ref MySqlCommand cmd, ref MySqlDataReader dr)
{
    DateTime log_time = DateTime.Now;
....
всякие проверки
....
    Console.WriteLine("{0} {1}: Init connection to DB.", log_time, mod_name);
    try
    {
        MySqlConnectionStringBuilder connBuilder = new MySqlConnectionStringBuilder();
        connBuilder.Add("Database", DB_NAME);
        connBuilder.Add("Data Source", DB_HOST);
        connBuilder.Add("User Id", DB_USER);
        connBuilder.Add("Password", DB_PASSWD);

        conn = new MySqlConnection(connBuilder.ConnectionString);
        conn.Open();

        Console.WriteLine("{0} {1}: DB initialized successfully.", log_time, mod_name);
    }
    catch (Exception e)
    {
       Console.WriteLine("{0} {1}: Error initializing DB connection - {2}", log_time, mod_name, e.Message);
    }
}

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

internal static void Add(struct_raw_point item)
{
    lock (queue_glob)
    {
        queue_glob.Add(item);
    }
}

а в теле парсера или где то там еще будем вызывать mod_db.Add(...);

настало время основного цикла "нити" main: в нем мы будем копировать данные из глобальной очереди в локальную, а уже из последней "вливать" данные в базу (на самом деле лениво копипастить код сюда, потому этого делать не буду).

Что из этого всего вышло? Да ничего хорошего - два потока (это пока что два, продолжение следует): основной и поток с БД. В основном потоке вызывается

mod_db.init();

и, например так, вносятся данные:

struct_raw_point cur_point = new struct_raw_point();

while (true)
{
    cur_point.raw_data = enc.GetBytes(DateTime.Now.ToString());
    mod_db.Add(cur_point);

    Thread.Sleep(1000);
}

Если будет интересно - будем развивать данный код smile Всем спасибо за внимание, старался быть не нудным.

P.S. задание на дом - запустить парсер в отдельном потоке smile

http://pastebin.com/jccHCZav - все сразу вместе

Отредактировано alexdob (07-09-2012 15:22:20)

Все, что нельзя написать на ассемблере, можно доделать паяльником (ц)

46

Re: Программирование. Как сделать сервер дома?

Я тут посреди всего просто выложу пока чистый не замусоренный примитивный пример html странички добавления одного маркера на карту

<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<style type="text/css">
  html { height: 100% }
  body { height: 100%; margin: 0px; padding: 0px }
  #map_canvas { height: 100% }
</style>


<script type="text/javascript"
    src="https://maps.google.com/maps/api/js?sensor=true">
</script>

</head>
<body>



  <div id="map_canvas" style="width:100%; height:100%"></div> <!--  контейнер с картой              -->
</body>

<script type="text/javascript">

 
  var myLatlng = new google.maps.LatLng(50.4505,30.5234);
  var myOptions = {
    zoom: 12,
    center: myLatlng,
    mapTypeId: google.maps.MapTypeId.ROADMAP,
  }
var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);   // Отображаем карту с опциями myOptions
   
var marker = new google.maps.Marker({              // параметры маркера. В ч. случае координаты маркера теже что и у карты - myLatlng
      position: myLatlng,
      title:"Hello Маркер!"
  });
 

  marker.setMap(map);                                    // добавляем маркер на карту вызываея setMap(map)

</script>

</html>


Потом можно менять и сам маркер и множество их добавлять. Чем я и займусь. А считывание портов пока отложу. Слишком запутано.

по материалам API google
https://developers.google.com/maps/docu … rial?hl=ru

Отредактировано Mars (15-09-2012 15:48:01)

47

Re: Программирование. Как сделать сервер дома?

http://lipatov.16mb.com/monitoring/

заготовка smile

Идея пока проста.  сделать два текстовых файла с долготой и широтой (с базами данных пока не разбирался). При запуске страницы, PHP считывает долготу широту в массив и передает их одним махом в яваскрипт. При загрузке страницы в кеше уже будут данные за последние сутки (минимум). Их останется только высветить или прятать по желанию и уже без тормозов. По идее скорость отображения должна быть высокой.

С динамикой онлайн отображения еще следует почитать.

И еще позже уже связать C# и WEB.

зы - не заметил вовремя - работает только в хроме. Почему другие не отображают нужно опять голову ломать..

Отредактировано Mars (15-09-2012 22:24:43)

48

Re: Программирование. Как сделать сервер дома?

Параллельно буду искать, но может кто быстрей подскажет.

Каким образом организовать корректней взаимодействие JS и PHP ?.
Допустим примитивно текстовые файлы будут наполняться координатами онлайн при движении объекта. Есть ли функция у PHP отслеживать изменения файла? или же запустить таймер в яваскрипте и дергать php (с помощью jQuery без перезагрузки)


____
..спустя 48 часов

Почти свершилось. Разобрался ка добавлять точки без перезагрузки!
Теперь осталось вспомнить с# чтобы парсить порт и все увязать между собой.   big_smile 
(принцип пока прост - яваскрипт+аякс будет опрашивать PHP каждые пару секунд, PHP проверять текстовый файл, если появляются точки возвращать данные к яваскрипт и точки будут добавляться.

н-да... знать надо много. Хотя сейчас уже не кажется все таким сложным  tongue

Отредактировано Mars (17-09-2012 00:18:32)

49

Re: Программирование. Как сделать сервер дома?

http://narod.ru/disk/61133901001.ab6b00 … w.rar.html

ссылка с исходником  ( пока еще реально разобраться).

50

Re: Программирование. Как сделать сервер дома?

копипаст многопоточного сервера на С#.теперь можно парсить данные и складывать в файл )

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net;
using System.Net.Sockets;

namespace MPserver
{
    class Program
    {
        static void Main(string[] args)
        
        {
            int port = 11000;
            string cmd;
            serverMN smn = new serverMN(port); // создаем класс serverMN и указываем что он принимает занчение port
            smn.Start();


            Console.WriteLine("Сервер создан...");

            while (true)
            {
                Console.WriteLine("<для выхода введите EXIT>");
                cmd = Console.ReadLine();
                if (cmd == "EXIT")
                {
                    return;
                }
            }
        }
    }

    //класс
    class serverMN
    {
        private Socket s;
        private int Port;
        public serverMN(int port)
        {
            Port = port;
        }

        private class ConnectionInfo
        {
            public Socket Socket;
            public Thread Thread;
        }
        //поле
        private Thread Th;
        //поле
        private List<ConnectionInfo> connect = new List<ConnectionInfo>();
        //конструтор
        public void Start()
        {
            SetupServerSocket();

            Th = new Thread(AcceptConnections);
            Th.IsBackground = true;
            Th.Start();
        }
        //конструктор
        private void SetupServerSocket()
        {
            int nCl = 0;


            //Получаем информацию о локальном компьютере
            IPEndPoint myEndPort = new IPEndPoint(IPAddress.Any, Port);


            // Получение имени компьютера.
            String host = System.Net.Dns.GetHostName();
            // узнаем свой ip-адреса.
            System.Net.IPAddress ip = System.Net.Dns.GetHostByName(host).AddressList[0];
            // Показ адреса 
            Console.WriteLine("IP адрес: {0}, порт: {1}", ip.ToString(), Port);

            //Создаем сокет, привязываем его к адресу



            s = new Socket(myEndPort.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

            s.Bind(myEndPort);
            s.Listen((int)SocketOptionName.MaxConnections);
            nCl = nCl + 1;
            // Console.WriteLine("(int)SocketOptionName.MaxConnections: " + (int)SocketOptionName.MaxConnections);
        }

        //конструктор
        private void AcceptConnections()
        {
            while (true)
            {
                //Принимаем соединение
                Socket socket = s.Accept();

                Console.WriteLine("Соединение установлено с:  " + socket.RemoteEndPoint);
                ConnectionInfo connection = new ConnectionInfo();
                connection.Socket = socket;
                //Создаем поток для получения данных
                connection.Thread = new Thread(ProcessConnection);
                connection.Thread.IsBackground = true;
                connection.Thread.Start(connection);
                //Сохраняем сокет
                lock (connect) connect.Add(connection);
            }
        }
        private void ProcessConnection(object state)
        {

            char ch; //промежуточное число
            

            ConnectionInfo connection = (ConnectionInfo)state;
            byte[] bufer = new byte[1024];
            string data;
            try
            {
                while (true)
                {
                    byte[] b = new byte[65535];
                    //int k = connection.Socket.Receive(b);

                    int bite_mes = connection.Socket.Receive(bufer);//количество байт в посылке

                    Console.WriteLine("Получено байт:" + bite_mes);
                    if (bite_mes > 0)
                    {
                        string simea = "";                          //первый способ вывода 
                        for (int i = 1; i < bite_mes; i++)          //каждый байт в символ
                        {
                            ch = Convert.ToChar(bufer[i]);
                            simea += Convert.ToString(ch);

                        }


                        Console.WriteLine("первый способ вывода:  " + simea);
                        data = Encoding.ASCII.GetString(bufer, 0, bite_mes).Trim();  // сразу целиком всю строку инкодируем и отображаем
                        //connection.Socket.Send(Encoding.ASCII.GetBytes(data));
                        Console.WriteLine(data);
                        Console.WriteLine("");
                    }
                    else if (bite_mes == 0)
                        return;
                }
            }
            catch (SocketException exc)
            {
                Console.WriteLine("Socket exception:" + exc.SocketErrorCode);
            }
            catch (Exception exc)
            {
                Console.WriteLine("Exception:" + exc);
            }
            finally
            {
                connection.Socket.Close();
                lock (connect) connect.Remove(connection);
            }
        }
    }
}

Отредактировано Mars (18-09-2012 12:01:03)