Как правильно отключить TCP соединение чтобы сервер не спами

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

Как правильно отключить TCP соединение чтобы сервер не спами

Сообщение anomal3 02 дек 2019, 15:27

Всем добра.
Помогите с задачей.
Всё пытаюсь сделать чат на Unity

Есть сервер, он работает. Подключает и отключает клиентов.
Консольный чат написал,
WF написал
и всё работает.
Но вот на Unity никак не получается разорвать соединение.
При попытке разорвать сединение, сервер сходит сума. Начинает спамить "пустышками"
Изображение

Что странно длина сообщения = 28 символам.
А байт 0.

Как видно в момент подключения длина сообщения и байты равны тому что написано

Изображение

Синтаксис:
Используется csharp
[SerializeField] private InputField Msg_all, Msg_enter;
 
    private string ip = "127.0.0.1";
    private int gen_chat_port = 15000;
    static string userName;
    static TcpClient client;
    static NetworkStream stream;
    Thread receiveThread = null;
    void Start()
    {
                Connect();
    }
   
    private void Disconnect()
    {
        if (stream != null)
            stream.Close();//отключение потока
        if (client != null)
            client.Close();//отключение клиента
       
    }
    private void OnApplicationQuit()
    {
#if UNITY_EDITOR
 
 
        //if (client != null)
        //{
        //    print("client isConnected  - " + client.Connected);
        //    client.Client.Close();
        //    client.Close();
        //    print("client isConnected  - " + client.Connected);
        //}
//Впринципе что и ниже client.Client.Disconnect(true);
 
        client.Client.Disconnect(true);
        //Stop playing the scene
        EditorApplication.isPlaying = false;
        print(EditorApplication.isPlaying);
        print("Клиент закрыт спустя " + Time.time + " секунд");
 
        Debug.Log("OnApplicationQuit() Прерывание потока. IsAlive-" + receiveThread.IsAlive);
        receiveThread.Abort();
        Debug.Log("Abort() IsAlive-" + receiveThread.IsAlive);
        // Ожидание прерывания
        receiveThread.Join();
        Debug.Log("Join() Основной поток прерван. IsAlive-" + receiveThread.IsAlive);
        Debug.Log("Клиент закрыт спустя " + Time.time + " секунд");
 
       
#endif
 
    }
 
    private void Connect()
    {
        userName = Environment.UserName;
 
        try
        {
            userName = Environment.UserName;
            client = new TcpClient();
 
            client.Connect(ip, gen_chat_port); //подключение клиента
            stream = client.GetStream(); // получаем поток
 
            string message = userName;
            byte[] data = Encoding.Unicode.GetBytes(message);
            stream.Write(data, 0, data.Length);
 
            // запускаем новый поток для получения данных
            receiveThread = new Thread(new ThreadStart(ReceiveMessage));
            receiveThread.Start(); //старт потока
            print("Добро пожаловать" + userName);//вывод сообщения
            SendMessage();
 
 
        }
        catch (Exception ex)
        {
            print(ex.Message);
        }
       
       
    }
    public void SendMessage()
    {
        string message = Msg_enter.text;
        byte[] data = Encoding.Unicode.GetBytes(message);
        stream.Write(data, 0, data.Length);
    }
 
    private async void ReceiveMessagelAsync()
    {
 
        await Task.Run(() => ReceiveMessage());
       
    }
 
    public void ReceiveMessage()
    {
        while (true)
        {
 
            try
            {
                byte[] data = new byte[64]; // буфер для получаемых данных
                StringBuilder builder = new StringBuilder();
                int bytes = 0;
                do
                {
                    bytes = stream.Read(data, 0, data.Length);
                    builder.Append(Encoding.Unicode.GetString(data, 0, bytes));
 
                }
                while (stream.DataAvailable);
                string message = builder.ToString();
 
                if (message != "")
                {
                    print(Environment.NewLine + message);
                   
 
                }
            }
            catch (Exception ex)
            {
                print("нет соединения\r\n" + ex.Message);
            }
        }
    }
}


Клиент свободно подключается, появляются сообщения. Но вот правильно отключить никак не могу.
Что я делаю не так?

P.S. и ещё. При двух одинаковых сбилденых версиях всё одинаково, только есть одно исключение, если выйти со второго такого клиента, сервер говорит что оба отключились.
А пока второй не вышел, сервер спамит пустышками
P.S.S На WinForms даже Метод Close не делаю, просто закрываю окно и все потоки прекращаются, прекрасно завершая работу
anomal3
UNец
 
Сообщения: 32
Зарегистрирован: 09 мар 2017, 15:29

Re: Как правильно отключить TCP соединение чтобы сервер не спами

Сообщение Saltant 02 дек 2019, 17:08

Ты уже определись, на WinForms делаешь чат или на Unity3D, код будет совсем другой.
Я на Google Play _https://play.google.com/store/apps/developer?id=Saltant
Аватара пользователя
Saltant
Старожил
 
Сообщения: 819
Зарегистрирован: 09 окт 2018, 16:40
Откуда: Химки
Skype: saltant1989
  • Сайт

Re: Как правильно отключить TCP соединение чтобы сервер не спами

Сообщение anomal3 02 дек 2019, 18:21

На Unity делаю. Просто я написал уже и на WF и консольный, чтобы проверить, всё ли я правильно написал.
А как будет на Unity?
anomal3
UNец
 
Сообщения: 32
Зарегистрирован: 09 мар 2017, 15:29

Re: Как правильно отключить TCP соединение чтобы сервер не спами

Сообщение Saltant 02 дек 2019, 18:24

anomal3 писал(а):А как будет на Unity?

Вот так: https://github.com/vis2k/Telepathy
Я на Google Play _https://play.google.com/store/apps/developer?id=Saltant
Аватара пользователя
Saltant
Старожил
 
Сообщения: 819
Зарегистрирован: 09 окт 2018, 16:40
Откуда: Химки
Skype: saltant1989
  • Сайт

Re: Как правильно отключить TCP соединение чтобы сервер не спами

Сообщение Jarico 02 дек 2019, 19:42

VK: _ttp://vk.com/salavan73
RakNet Client-Server Unity3D: _https://vk.cc/9xuZp8
RakNet Client-Server Github: _ttp://github.com/ep1s0de3/RakNet_Networking
RakNet Unity: _https://www.youtube.com/channel/UCPQ04Xpbbw2uGc1gsZtO3HQ
Jarico
UNIверсал
 
Сообщения: 431
Зарегистрирован: 06 янв 2019, 17:37
Откуда: 0xDEAD
Skype: none
  • Сайт

Re: Как правильно отключить TCP соединение чтобы сервер не спами

Сообщение anomal3 02 дек 2019, 22:40

Saltant писал(а):
anomal3 писал(а):А как будет на Unity?

Вот так: https://github.com/vis2k/Telepathy

Хороший помер. Попробую разобраться


Нет живого примера. От скомпилиной версии вытекли глаза от фиолетового цвета.
А от графики стошнило, даже протестировать систему не смог.
Есть более живой пример взаимодействия?

Я Вам искренне благодарен. Но Готовое решение - есть готовое решение, а если что-то отвалится?
Или кто-то найдёт дюп какой или баг и будет им пользоваться? Шуршать в чужом коде и пытаться разобраться что автор курил в ту ночь?

Да и пока не пойму на своём примере, почему происходит та или иная ошибка, смысл браться за чужие?
TCP для меня новая планета. Хочу освоится на своих пока что примерах.

А за готовое решение ЛОЙС!!

У вас лично есть мысли по моему вопросу?
anomal3
UNец
 
Сообщения: 32
Зарегистрирован: 09 мар 2017, 15:29

Re: Как правильно отключить TCP соединение чтобы сервер не спами

Сообщение anomal3 02 дек 2019, 22:41

Saltant писал(а):Ты уже определись, на WinForms делаешь чат или на Unity3D, код будет совсем другой.

Скажи в чём моя ошибка?
Как я не правильно отключаю клиента?
anomal3
UNец
 
Сообщения: 32
Зарегистрирован: 09 мар 2017, 15:29

Re: Как правильно отключить TCP соединение чтобы сервер не спами

Сообщение Saltant 03 дек 2019, 08:19

Ну поставь точки остановки на сервере и клиенте и поймешь что не так. Не забудь еще про особенность игрового движка, что нельзя получить доступ к объекту MonoBehaviour не из основного потока. Об этом не много подробней я писал в этой теме viewtopic.php?f=105&t=51238
Я на Google Play _https://play.google.com/store/apps/developer?id=Saltant
Аватара пользователя
Saltant
Старожил
 
Сообщения: 819
Зарегистрирован: 09 окт 2018, 16:40
Откуда: Химки
Skype: saltant1989
  • Сайт

Re: Как правильно отключить TCP соединение чтобы сервер не спами

Сообщение Jarico 03 дек 2019, 10:51

anomal3 писал(а):
Saltant писал(а):
anomal3 писал(а):А как будет на Unity?

Вот так: https://github.com/vis2k/Telepathy

Хороший помер. Попробую разобраться


Нет живого примера. От скомпилиной версии вытекли глаза от фиолетового цвета.
А от графики стошнило, даже протестировать систему не смог.
Есть более живой пример взаимодействия?

Я Вам искренне благодарен. Но Готовое решение - есть готовое решение, а если что-то отвалится?
Или кто-то найдёт дюп какой или баг и будет им пользоваться? Шуршать в чужом коде и пытаться разобраться что автор курил в ту ночь?

Да и пока не пойму на своём примере, почему происходит та или иная ошибка, смысл браться за чужие?
TCP для меня новая планета. Хочу освоится на своих пока что примерах.

А за готовое решение ЛОЙС!!

У вас лично есть мысли по моему вопросу?


Какие баги!? Это готовое решение, тебе осталось написать взаимодействие клиента и сервера.... Пишешь свои айдишники пакетов и отправляешь а потом обрабатываешь на принимаемой стороне. Как нет живого примера? Там есть 2 скрипта (1 клиент, 1 сервер) запускаешь каждый из скриптов и смотришь результат
VK: _ttp://vk.com/salavan73
RakNet Client-Server Unity3D: _https://vk.cc/9xuZp8
RakNet Client-Server Github: _ttp://github.com/ep1s0de3/RakNet_Networking
RakNet Unity: _https://www.youtube.com/channel/UCPQ04Xpbbw2uGc1gsZtO3HQ
Jarico
UNIверсал
 
Сообщения: 431
Зарегистрирован: 06 янв 2019, 17:37
Откуда: 0xDEAD
Skype: none
  • Сайт

Re: Как правильно отключить TCP соединение чтобы сервер не спами

Сообщение Saltant 03 дек 2019, 15:53

Jarico, использовать RakNet в случае чатика слишком сильно. Telepathy более "прозрачен" даже для неопытного юзера чтоль, хз как правильно выразиться =)
Я на Google Play _https://play.google.com/store/apps/developer?id=Saltant
Аватара пользователя
Saltant
Старожил
 
Сообщения: 819
Зарегистрирован: 09 окт 2018, 16:40
Откуда: Химки
Skype: saltant1989
  • Сайт

Re: Как правильно отключить TCP соединение чтобы сервер не спами

Сообщение Jarico 03 дек 2019, 17:12

Saltant писал(а):Jarico, использовать RakNet в случае чатика слишком сильно. Telepathy более "прозрачен" даже для неопытного юзера чтоль, хз как правильно выразиться =)


А почему? Чего там сильного? Запустил чат (клиент или сервер), ввёл адрес сервера, подключился, отправил пакеты с опред. номерами, обработал, отправил обратно... Схема проще простого, не нужно даже возиться с сокетами + к этому имеется низкоуровневая статистика по трафику
VK: _ttp://vk.com/salavan73
RakNet Client-Server Unity3D: _https://vk.cc/9xuZp8
RakNet Client-Server Github: _ttp://github.com/ep1s0de3/RakNet_Networking
RakNet Unity: _https://www.youtube.com/channel/UCPQ04Xpbbw2uGc1gsZtO3HQ
Jarico
UNIверсал
 
Сообщения: 431
Зарегистрирован: 06 янв 2019, 17:37
Откуда: 0xDEAD
Skype: none
  • Сайт

Re: Как правильно отключить TCP соединение чтобы сервер не спами

Сообщение Saltant 03 дек 2019, 17:26

Да мне то всё это понятно, но вспомнил я себя когда только начал изучать как работает сеть и протоколы - РакНет мне вообще не зашел, а Телепати я сходу понял. Так что и топик стартеру посоветовал то что мне было легче доступно когда изучал сабж.
Я на Google Play _https://play.google.com/store/apps/developer?id=Saltant
Аватара пользователя
Saltant
Старожил
 
Сообщения: 819
Зарегистрирован: 09 окт 2018, 16:40
Откуда: Химки
Skype: saltant1989
  • Сайт

Re: Как правильно отключить TCP соединение чтобы сервер не спами

Сообщение Jarico 03 дек 2019, 18:15

anomal3 писал(а):Клиент свободно подключается, появляются сообщения. Но вот правильно отключить никак не могу.
Что я делаю не так?


Видимо ты закрываешь сокет (он не принимает данные) но Task.Run до сих пор работает и спамит сообщения потому что while (stream.DataAvailable); цикл продолжается потому что DataAvailable == true, следовательно если DataAvailable == true то переменная Position в базовом классе равна 0 а это означает что поток не прочтён и поток готов читать данные

Вроде логика верна
VK: _ttp://vk.com/salavan73
RakNet Client-Server Unity3D: _https://vk.cc/9xuZp8
RakNet Client-Server Github: _ttp://github.com/ep1s0de3/RakNet_Networking
RakNet Unity: _https://www.youtube.com/channel/UCPQ04Xpbbw2uGc1gsZtO3HQ
Jarico
UNIверсал
 
Сообщения: 431
Зарегистрирован: 06 янв 2019, 17:37
Откуда: 0xDEAD
Skype: none
  • Сайт

Re: Как правильно отключить TCP соединение чтобы сервер не спами

Сообщение anomal3 04 дек 2019, 08:19

Saltant писал(а):Ну поставь точки остановки на сервере и клиенте и поймешь что не так. Не забудь еще про особенность игрового движка, что нельзя получить доступ к объекту MonoBehaviour не из основного потока. Об этом не много подробней я писал в этой теме viewtopic.php?f=105&t=51238

Да дело именно в потоке. Спасибо за ответы. Дело оказалось в том что я пытался получить доступ к InputField не из основного потока. Поставив переменную всё прекрасно заработало.
RakNet я посмотрел документацию и прифигел, оказывается он даже на c++ есть.
Я про баги я говорил, что задержка идёт, дёргается всё. Может кстати это даже я дёргался.

И спам сервера был потому что на сервере я не проверял нулевой байт. Когда байт = 0 значит клиент хочет отключиться, и пора разрывать соединение, но я этого не делал
Ещё раз спасибо за ответы
anomal3
UNец
 
Сообщения: 32
Зарегистрирован: 09 мар 2017, 15:29

Re: Как правильно отключить TCP соединение чтобы сервер не спами

Сообщение anomal3 04 дек 2019, 08:33

Saltant писал(а):Ну поставь точки остановки на сервере и клиенте и поймешь что не так. Не забудь еще про особенность игрового движка, что нельзя получить доступ к объекту MonoBehaviour не из основного потока. Об этом не много подробней я писал в этой теме viewtopic.php?f=105&t=51238

хмм. А я на Англоязычном форуме нашёл ответ. Один из комментов был : "Нельзя мол объекты использовать не в главном потоке". Ещё было добавлено мол есть кое-какие исключения, но вот какие хз не написано

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

А задвался вопросом ?
Что будет если поток задействован будет в DLL и эта dll будет вынесена отдельно допустим в StreamingAsstes.

p.s. про 80 мс почитал :))
Но сразу в голову идёт игра от 1C (Caliber)
Задержка в 7-14 мс, как говорили разработчики, весь процесс на сервере, клиент просто отображает данные
anomal3
UNец
 
Сообщения: 32
Зарегистрирован: 09 мар 2017, 15:29

След.

Вернуться в Почемучка

Кто сейчас на конференции

Сейчас этот форум просматривают: Yandex [Bot] и гости: 30