1

Тема: Роздуми щодо клієнт-серверної взаємодії.

От слухайте. Раніше я був дурним і т.д. і робив так - клієнт посилає массив байт, в котрому спершу йде стрічка(команда), а потім дані, наприклад {"lgn","login",password}. А на сервері, є здоровий блок switch з мілліонами мілліонів case'ів, типу

switch(some_string)
{
....
case "lgn": TryToLogin(log,pass) break;
....
}

ну чи якось так. І зрозуміло, що, якщо перед цим case'ом буде ще 100, то буде 100 непотрібних перевірок. Ооот. Зара я  використовую клас Dictionary<string key,MyDelegate del>, ну ви зрозуміли, тепер, коли на сервер приходять дані, я витягую команду з массиву байт і роблю щось типу

dict["lgn"](log,pass);

Ну ви зрозуміли. Коду набагато менше і швидше працює. Але є одне але. Методи, котрі мають виконуватися на сервері, можуть бути різної структури. Наприклад, ви тільки що побачили метод TryToLogin(string log, string pass), насправді він ще повертає значення типу int. І аби запихнути делегат цього методу в словник, треба створити відповідний делегат, в котрому описується, що він має повертати значення, та що він приймає два значення типу string. Але якщо ж методи можуть бути різними, то що, мені тепер створювати цілу купу відповідних делегатів????
В мене з`явилась ідея, зробити здоровий клас, котрий буде виконувати роль аргумента метода і назвати його щось типу ArgForServer, та створити метод-результат, котрий буде повертати якесь значення після обробки методом отриманих даних, якщо треба, і назвати його щось типу ResultFromServer. Ці два класа мають мати поля під всі значення, котрі можуть передаватись клієнтом серверу та навпаки, наприклад,

string login;
string password;
int id;
string message;
int addressee_id;
.....

ну типу такий собі універсальний аргумент на всі випадки життя. І дивіться, якщо я хочу відправити запит на логін, то я створюю екземпляр цього класу, і присвоюю потрібним полям потрібні значеня і тут в мене постає питання. Якщо я маю в класі, наприклад, чотири поля типу int, потім ініціалізую екземпляр цього класу, то в пам'яті буде виділено місце під всі чотири поля типу int?

2

Re: Роздуми щодо клієнт-серверної взаємодії.

FakiNyan написав:

І зрозуміло, що, якщо перед цим case'ом буде ще 100, то буде 100 непотрібних перевірок.

От і виросло покоління програмістів... кгм...
Ви не повірите, що робить switch всередині. Просто не повірите. Там є масив, причому для рядків - хешований. Точно як те, що ви робите явно, тільки конструкціями мови (а отже, оптимізатор може ще трохи попрацювати із ними).

Ну і для десеріалізації в будь-якому разі доведеться використовувати switch. А далі - гугліть "ООП поліморфізм C#".

FakiNyan написав:


Якщо я маю в класі, наприклад, чотири поля типу int, потім ініціалізую екземпляр цього класу, то в пам'яті буде виділено місце під всі чотири поля типу int?

Звісно що так.

3

Re: Роздуми щодо клієнт-серверної взаємодії.

koala написав:
FakiNyan написав:

І зрозуміло, що, якщо перед цим case'ом буде ще 100, то буде 100 непотрібних перевірок.

От і виросло покоління програмістів... кгм...
Ви не повірите, що робить switch всередині. Просто не повірите. Там є масив, причому для рядків - хешований. Точно як те, що ви робите явно, тільки конструкціями мови (а отже, оптимізатор може ще трохи попрацювати із ними).

Ну і для десеріалізації в будь-якому разі доведеться використовувати switch. А далі - гугліть "ООП поліморфізм C#".

FakiNyan написав:


Якщо я маю в класі, наприклад, чотири поля типу int, потім ініціалізую екземпляр цього класу, то в пам'яті буде виділено місце під всі чотири поля типу int?

Звісно що так.

не повірите, нам ніхто не казав, як працює той switch. Все що казали, то це те, що його краще юзати замість if, якщо там тре багато писати if else. І навіщо switch для десеріалізації? І як тоді зробити супер-аргумент?

4

Re: Роздуми щодо клієнт-серверної взаємодії.

FakiNyan написав:


не повірите, нам ніхто не казав, як працює той switch. Все що казали, то це те, що його краще юзати замість if, якщо там тре багато писати if else.

Правду казали. Чого ж ви не повірили?

FakiNyan написав:

І навіщо switch для десеріалізації?

От саме для цього: розібрати, що саме надійшло, і вибрати потрібну гілку.

FakiNyan написав:

І як тоді зробити супер-аргумент?

Не треба його робити. Почитайте вже про поліморфізм.

5

Re: Роздуми щодо клієнт-серверної взаємодії.

koala написав:
FakiNyan написав:


не повірите, нам ніхто не казав, як працює той switch. Все що казали, то це те, що його краще юзати замість if, якщо там тре багато писати if else.

Правду казали. Чого ж ви не повірили?

FakiNyan написав:

І навіщо switch для десеріалізації?

От саме для цього: розібрати, що саме надійшло, і вибрати потрібну гілку.

FakiNyan написав:

І як тоді зробити супер-аргумент?

Не треба його робити. Почитайте вже про поліморфізм.

ТАК Я ПОВІРИВ!!!!! Але там нічо не було чути про хеш-таблицю ок да? Щось я не можу допетрати, навіщо мені switch для серіалізації, дивіться, як мона клас серіалізувати

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading.Tasks;

namespace serialize
{
    class Program
    {
        static void Main(string[] args)
        {
            byte[] buff=new byte[1024];
            IFormatter iFormatter;
            MemoryStream ms;
            Stream stream=new MemoryStream(buff);
            character myChar=new character("assosen",80);
            iFormatter = new BinaryFormatter();
            iFormatter.Serialize(stream,myChar);
            
            ser s = new ser(buff);
            s.ShowInfo();
            Console.Read();
        }
    }

    [Serializable]
    class character
    {
        private string name;
        private int lvl;

        public character(string name, int lvl)
        {
            this.name = name;
            this.lvl = lvl;
        }

        public void ShowInfo()
        {
            Console.WriteLine("Name: "+name+"\nLevel: "+lvl);
        }
    }

    class ser
    {
        private character myChar;

        public ser(byte[] buff)
        {
          IFormatter iFormatter = new BinaryFormatter();
          Stream s = new MemoryStream(buff);
            myChar = (character)iFormatter.Deserialize(s);
        }

        public void ShowInfo()
        {
            myChar.ShowInfo();
        }
        
    }
}

Гаразд, я почитаю про поліморфізм!!!!

Post's attachments

ss (2013-10-29 at 11.41.16).png 22.6 kb, 224 downloads since 2013-10-29 

6

Re: Роздуми щодо клієнт-серверної взаємодії.

FakiNyan написав:
koala написав:
FakiNyan написав:

І навіщо switch для десеріалізації?

От саме для цього: розібрати, що саме надійшло, і вибрати потрібну гілку.

Щось я не можу допетрати, навіщо мені switch для серіалізації, дивіться, як мона клас серіалізувати

[іmg]facepalm.jpg[/іmg]

7

Re: Роздуми щодо клієнт-серверної взаємодії.

koala написав:
FakiNyan написав:
koala написав:

От саме для цього: розібрати, що саме надійшло, і вибрати потрібну гілку.

Щось я не можу допетрати, навіщо мені switch для серіалізації, дивіться, як мона клас серіалізувати

[іmg]facepalm.jpg[/іmg]

ну десеріалізації, але всеодно не зрозуміло навіщо воно мені, якщо я можу використати чудовий iFormatter

8

Re: Роздуми щодо клієнт-серверної взаємодії.

угу, тобто ви пропонуєте робити типу отак ага?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace polymorph
{
    class Program
    {
        static void Main(string[] args)
        {
            List<BaseArgs> bc = new List<BaseArgs>();
            bc.Add(new tryToLogin("XxVasyaxX","mijparol"));
            bc.Add(new tryToCreateNewChar("KiSa4kA",666));
            foreach (var baseCommand in bc)
            {
                baseCommand.Showinfo();
            }
            Console.Read();
        }
    }

    abstract class BaseArgs
    {
        abstract public void Showinfo();
    }

    class tryToLogin : BaseArgs
    {
        private string log;
        private string pass;

        public tryToLogin(string log, string pass)
        {
            this.log = log;
            this.pass = pass;
        }
        public override void Showinfo()
        {
            Console.WriteLine("log = "+log+"\npass = "+pass+"\n");
        }
    }

    class tryToCreateNewChar : BaseArgs
    {
        private string nickname;
        private int userId;

        public tryToCreateNewChar(string nickname, int userId)
        {
            this.nickname = nickname;
            this.userId = userId;
        }

        public override void Showinfo()
        {
            Console.WriteLine("nickname = " + nickname + "\nuserId = " + userId+"\n");
        }
    }
}

9

Re: Роздуми щодо клієнт-серверної взаємодії.

Ну так правильно - для серіалізації все добре. Питання в десеріалізації.

10

Re: Роздуми щодо клієнт-серверної взаємодії.

koala написав:

Ну так правильно - для серіалізації все добре. Питання в десеріалізації.

НУ так а що не так? у клієнта та сервера є описання класу. Клієнт серіалізує. а сервер десеріалізує. в чому проблема? а то я не розумію(((

11

Re: Роздуми щодо клієнт-серверної взаємодії.

Ну як не бачите - то, цілком можливо, це я помиляюся. Покажіть, як ви десеріалізуєте дані.

12

Re: Роздуми щодо клієнт-серверної взаємодії.

koala написав:

Ну як не бачите - то, цілком можливо, це я помиляюся. Покажіть, як ви десеріалізуєте дані.

 class ser
    {
        private character myChar;
 
        public ser(byte[] buff)
        {
          IFormatter iFormatter = new BinaryFormatter();
          Stream s = new MemoryStream(buff);
            myChar = (character)iFormatter.Deserialize(s);
        }
 
        public void ShowInfo()
        {
            myChar.ShowInfo();
        }
        
    }

13 Востаннє редагувалося koala (29.10.2013 16:03:12)

Re: Роздуми щодо клієнт-серверної взаємодії.

Як бачите - я був правий: я помилявся. .NET вже такий розумний, що вміє це сам робити, відчуваю, у версії .NET 8.0 буде тільки один метод - "зробити офігенним". Ну, і решта, для сумісності із старими програмами :)
Але в такому разі - нафіга вам той супер-аргумент? Серіалізуєте об'єкти, пхаєте їх мережею, десеріалізуєте на місці і все працює.

14

Re: Роздуми щодо клієнт-серверної взаємодії.

koala написав:

Як бачите - я був правий: я помилявся. .NET вже такий розумний, що вміє це сам робити, відчуваю, у версії .NET 8.0 буде тільки один метод - "зробити офігенним". Ну, і решта, для сумісності із старими програмами :)
Але в такому разі - нафіга вам той супер-аргумент? Серіалізуєте об'єкти, пхаєте їх мережею, десеріалізуєте на місці і все працює.

ну мені був потрібен супер-аргумент, щоб не робити багато різних делегатів для методів, котрі обробляють отримані дані на сервері. Ну то щоб всі методи приймали один аргумент одного типу, ну і щоб повертали аргумент одного й того самого типу. Тоді просто один делегат для всіх таких методів зробив, і позапихував ті делегати в той, в словник.

Прихований текст

http://не-дійсний-домен/52Qqd.png

15

Re: Роздуми щодо клієнт-серверної взаємодії.

Робите в кожному нащадку вашого "SuperArg" метод "execute" без параметрів, серіалізуєте його, надсилаєте, десереалізуєте і виконуєте.

16

Re: Роздуми щодо клієнт-серверної взаємодії.

koala написав:

Робите в кожному нащадку вашого "SuperArg" метод "execute" без параметрів, серіалізуєте його, надсилаєте, десереалізуєте і виконуєте.

ну без параметрів не вийде, бо по-перше цей метод має мати сокет певного клієнта, аби відправити йому відповідь від сервера, або навіть має мати массив тих сокетів, щоб відправити повідомлення від одного клієнта всім іншим, а ще в деяких випадках треба звертатись до бази даних, так що параметр один все ж таки тре зробити

17

Re: Роздуми щодо клієнт-серверної взаємодії.

А що, дати методу самому вибирати сокети не можна?

18

Re: Роздуми щодо клієнт-серверної взаємодії.

koala написав:

А що, дати методу самому вибирати сокети не можна?

хм, можна ХД

19

Re: Роздуми щодо клієнт-серверної взаємодії.

koala написав:

Робите в кожному нащадку вашого "SuperArg" метод "execute" без параметрів, серіалізуєте його, надсилаєте, десереалізуєте і виконуєте.

чуйте, але ж в нас є методи, котрі роблять запит до бази даних, а для цього потрібно створити об'єкт для підключення до БД і підключити відповідну бібліотеку, то що, мені створювати це все і на клієнті? ну тобто в клієнті є класс, в котрому є метод для роботи з базою даних, в ньому написано, що він бере такий об'єкт для підключення до БД і робить там щось, так мені ж це потрібно робити тільки на сервері, а прийдеться створювати ті об'єкти для підключення до БД і на клієнті? Воно буде взагалі нормально працювати після десеріалізації на сервері?

20

Re: Роздуми щодо клієнт-серверної взаємодії.

Звісно що ні. У вас є об'єкт "повідомлення" (SuperArg, якщо вам так зручно) з нащадками. Це повідомлення, звісно, має смикати не безпосередньо базу, а певний об'єкт, який і надає доступ до бази чи чогось там. Далі, гадаю, безглуздо розмовляти без коду.