Форум программистов, компьютерный форум, киберфорум
Unity, Unity3D
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.67/15: Рейтинг темы: голосов - 15, средняя оценка - 4.67
2 / 2 / 1
Регистрация: 09.01.2015
Сообщений: 382
1

Многопоточный сокет и Создание объектов в Unity

13.04.2018, 00:52. Показов 2774. Ответов 25
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Добрый день ! Так я и не нашел реализации .
У меня сокет . Чтение данных происходит в другом потоке . После обработки данных пытаюсь создать объект или сцену и получаю : LoadSceneAsyncNameIndexInternal can only be called from the main thread. или get_isActiveAndEnabled can only be called from the main thread.
Как с этим бороться ?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
13.04.2018, 00:52
Ответы с готовыми решениями:

Unity 5. Как сделать создание и удаление объектов
Пишу скрипты на C# хочу сделать ферму но не знаю как сделать создание объекта пшеница на...

Деформация объектов в Unity
Всем привет! Вопрос есть такой: Как сделать в Unity3D что бы объекты могли деформироваться?...

Отслеживание объектов Vuforia и Unity
Здравствуйте, на этом видео, показано как создать сканирование и отслеживание объектов с помощью...

Координаты дочерних объектов в Unity
Очень сильно раздражает,что дочерние объекты берут как точку начала координат позицию...

25
753 / 600 / 204
Регистрация: 06.08.2015
Сообщений: 2,432
13.04.2018, 12:02 2
Создавать очередь в основном и передавать из потока в контроллер сцены
0
2 / 2 / 1
Регистрация: 09.01.2015
Сообщений: 382
13.04.2018, 16:39  [ТС] 3
Queue<Action> ?? а есть пару примеров ?
0
2 / 2 / 1
Регистрация: 09.01.2015
Сообщений: 382
14.04.2018, 19:27  [ТС] 4
нашел такой подход ( правда на java ) https://devtribe.ru/p/unity/unity-multithread
Я так же пытался синхронизировать через lock . но не вышло ((
0
753 / 600 / 204
Регистрация: 06.08.2015
Сообщений: 2,432
14.04.2018, 19:34 5
Но там же всё просто, как три копейки...
0
2 / 2 / 1
Регистрация: 09.01.2015
Сообщений: 382
14.04.2018, 19:35  [ТС] 6
https://answers.unity.com/ques... aging.html
И как первое только на C#
http://www.unity3d.ru/distribu... =5&t=33905

Просто не могу понять как это работает .
0
753 / 600 / 204
Регистрация: 06.08.2015
Сообщений: 2,432
14.04.2018, 20:19 7
С понятием "делегат" знаком? Что такое System.Action знаешь?
0
2 / 2 / 1
Регистрация: 09.01.2015
Сообщений: 382
14.04.2018, 20:28  [ТС] 8
Да . Просто допустим у меня 2 сокета . т.е 2 дополнительных потока . Как я понял из статьи что создается Список методов . Потом поток тормозится . потом в Update происходит проверка на методы и они выполняются .

Добавлено через 2 минуты
вот мой класс Socket
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using UnityEngine;
 
 
public class SocetConnect  
{
      //---------------------------------------------------------------------------------------------------
       public event EventHandler<SocketEventArgs> connected;
       protected virtual void Connected(SocketEventArgs e) { if (connected != null) connected(this, e); }
       //---------------------------------------------------------------------------------------------------
       public event EventHandler<SocketEventArgs> closed;
       protected virtual void Closed(SocketEventArgs e) { if (closed != null) closed(this, e); }
       //---------------------------------------------------------------------------------------------------
       public event EventHandler<SocketEventArgs> ioError;
       protected virtual void IoError(SocketEventArgs e) { if (ioError != null) ioError(this, e); }
       //---------------------------------------------------------------------------------------------------
       public event EventHandler<SocketEventArgs> incomingData;
       protected virtual void IncomingData(SocketEventArgs e) { if (incomingData != null) incomingData(this, e); }
       //---------------------------------------------------------------------------------------------------
       public event EventHandler<SocketEventArgs> outgoingData;
       protected virtual void OutgoingData(SocketEventArgs e) { if (outgoingData != null) outgoingData(this, e); }
       //---------------------------------------------------------------------------------------------------
       public event EventHandler<SocketEventArgs> needNOP;
       protected virtual void NeedNOP(SocketEventArgs e) { if (needNOP != null) needNOP(this, e); }
       //---------------------------------------------------------------------------------------------------     
 
  /*  public delegate void EventHandler(SocketEventArgs e);
 
    public event EventHandler connected;
    public event EventHandler closed;
    public event EventHandler incomingData;
    public event EventHandler outgoingData;*/
 
    Socket socket;
    public string unpack ;
    UnpackChat unpackchat = new UnpackChat();
    UnpackGame unpackgame = new UnpackGame();
    public Thread _thread;
    public bool isConnected = false;
 
    private void Start()
    {
        isConnected = false;
        unpack = "";
    }
 
    public void Connect(ServerObject serverObject)
    {
        try
        {
            unpack = serverObject.unpack; // Тип распаковки принятых данных 
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // Создаем Tcp socket
            IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse(serverObject.host), serverObject.port); // Создаем точку подключения 
            socket.ReceiveBufferSize = 65535; // Размер буфера сокета , куда приходят данные 
            socket.Connect(ipPoint); // Коннектимся 
            _thread = new Thread(ReceiveData);
            _thread.IsBackground = true;
            _thread.Start();
            isConnected = true;
            Connected(new SocketEventArgs("<Connected/>")); // Событие то-что законнектились 
        }
        catch (Exception e)
        {
            Debug.Log(e);
        }
    }
 
    public void Disconnect()
    {
        if (isConnected)
        {
            _thread.Interrupt();
            socket.Shutdown(SocketShutdown.Both); // Приостанавливаем прием/передачу   
            socket.Disconnect(true); // Отключаем сокет 
          //  socket.Close();
            //socket.Dispose();
            isConnected = false;
            Closed(new SocketEventArgs("<Disconnected/>")); // Событие дисконекта 
        }
    }
 
    public bool Status()
    {
            return isConnected;
    }
 
    public void SendData(string data) // Передача 
    {
        if (socket.Connected)
        {
            byte[] array = Encoding.UTF8.GetBytes(data + "\x00");
            socket.Send(array);
            Debug.Log("OUT : " + data);
            OutgoingData(new SocketEventArgs(data));
        }
    }
 
    public void ReceiveData() // Прием 
    {
        byte[] data = new byte[256]; // Размер буфера 
        int bytes = 0; // Кол-во считанных байт 
        string packet = ""; // Строка для хранения пакета 
        char stopChar = Convert.ToChar(0x00); // Конец пакета 
 
        while (socket.Connected)
        {
            while (socket.Available > 0)
            {
                bytes = socket.Receive(data, data.Length, SocketFlags.None);
                packet += Encoding.UTF8.GetString(data, 0, bytes);
            }
            if (packet.Length > 1)
            {
                if (packet[packet.Length - 1] == Convert.ToChar(0x00)) // Если у нас что - то есть и оно заканчивается на 0x00 
                {
                    packet = packet.Replace("\x0D" + "\x0A", "");
                    string[] packets = packet.Split(new char[] { stopChar }, StringSplitOptions.RemoveEmptyEntries);
                    foreach (string s in packets) // перебираем пакеты 
                    {
                        switch (unpack)
                        {
 
                            case "GAME":
                                IncomingData(new SocketEventArgs(unpackgame.convert(s))); // вызов события 
                                break;
                            case "CHAT":
                                IncomingData(new SocketEventArgs(unpackchat.convert(s))); // вызов события 
                                break;
                            default:
                                IncomingData(new SocketEventArgs(s)); // вызов события 
                                break;
                        }
                    }
 
                    packet = ""; // Обнуляем 
                    }
                }
            }
        }
    }
}
Добавлено через 3 минуты
Просто я пытаюсь понять на каком этапе внедрить этот способ .
Вот допустим обработка в синглтоне того что пришло
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
   public void onIncomingGameMessage(object sender, SocketEventArgs e)
    {
        Debug.Log("IN : " + e.message);
        string typePacket = e.doc.FirstChild.Name;
        switch (typePacket)
        {
 
            case "ERROR":
                //     EventManager.dispatchEvent(typePacket, "IN " + typePacket + " : " + e.message);
                onGameErrorCode(e.doc.FirstChild.Attributes[0].Value.ToString());
                break;
            case "KEY":
                //     EventManager.dispatchEvent(typePacket, "IN " + typePacket + " : " + e.message);
                security.cipherKey = e.doc.FirstChild.Attributes[0].Value.ToString();
                game_sock.SendData(security.game_connect());
                break;
            case "OK":
                //      EventManager.dispatchEvent(typePacket, "IN " + typePacket + " : " + e.message);
                ses = e.doc.FirstChild.Attributes[1].Value.ToString();
                game_sock.SendData(toServer.getme);
                break;
            case "MYPARAM":
                //       EventManager.dispatchEvent(typePacket, "IN " + typePacket + " : " + e.message);
                if (e.doc.FirstChild.ChildNodes.Count > 0)
                {
                    game_sock.SendData(toServer.chat);
                }
             //   SceneManager.LoadScene("Game");
                break;
            case "CHAT":
                //          EventManager.dispatchEvent(typePacket, "IN " + typePacket + " : " + e.message);
                chat_sock = new SocetConnect();
                chat_sock.connected += onEstablishChatConnection;
                chat_sock.incomingData += onIncomingChatMessage;
                chat_sock.outgoingData += onOutgoingChatMessage;
                chat_sock.Connect(new ServerObject(Dns.GetHostEntry(e.doc.FirstChild.Attributes[0].Value).AddressList[0].ToString(), 5190, "CHAT"));
                chat_sock.SendData("<CHAT ses=\"" + ses + "\" l=\"SmokeI\" />");
                game_sock.SendData(toServer.mr);
                break;
            case "MR":
                //          EventManager.dispatchEvent(typePacket, "IN " + typePacket + " : " + e.message);
                game_sock.SendData(toServer.bgd);
                break;
            case "BGD":
                //         EventManager.dispatchEvent(typePacket, "IN " + typePacket + " : " + e.message);
                game_sock.SendData(toServer.info);
                game_sock.SendData(toServer.info1);
                //  game_sock.SendData(toServer.getloc);
                break;
            default:
                //         EventManager.dispatchEvent("Debug", e.message);
                break;
        }
    }
0
753 / 600 / 204
Регистрация: 06.08.2015
Сообщений: 2,432
14.04.2018, 20:30 9
Список делегатов. Из потока блокируется список (потокобезопасность), добавляется делегат, разблокируется список. В апдейте твой скрипт-компонент блокирует список, проверяет его и вызывает его делегаты (это уже майн тред, всё в порядке) и разблокирует после этого список.
0
2 / 2 / 1
Регистрация: 09.01.2015
Сообщений: 382
14.04.2018, 20:31  [ТС] 10
Т.е получается что если данные переданы из другого потока . то все действия по обработке так же будут в другом потоке .
Т.е надо произвести синхронизацию на уровне приема данных с сокета и обрабатывать даннные в основном потоке .
0
753 / 600 / 204
Регистрация: 06.08.2015
Сообщений: 2,432
14.04.2018, 20:33 11
Анонимный делегат ()=>{GameController.Instance.AddChatMessage(fromPlayer, textPlayer);} сработает как надо, хоть и параметры из потока заданы
0
2 / 2 / 1
Регистрация: 09.01.2015
Сообщений: 382
14.04.2018, 20:44  [ТС] 12
Хотя по идее можно в моем Классе socket сделать лист грубо говоря событий. и передавать уже их

Добавлено через 1 минуту
Только мой класс надо добавить MonoBehaviour . И воткнуть Update
0
753 / 600 / 204
Регистрация: 06.08.2015
Сообщений: 2,432
14.04.2018, 20:53 13
Контроллер должен быть в майн потоке.

Добавлено через 41 секунду
Из потока в контроллер передавать делегат, чтобы вызов был из майна.

Добавлено через 26 секунд
Пофиг где назначен делегат, важна точка вызова его.
0
2 / 2 / 1
Регистрация: 09.01.2015
Сообщений: 382
16.04.2018, 00:43  [ТС] 14
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using UnityEngine;
 
 
public class SocetConnect : MonoBehaviour 
{
      //---------------------------------------------------------------------------------------------------
       public event EventHandler<SocketEventArgs> connected;
       protected virtual void Connected(SocketEventArgs e) { if (connected != null) connected(this, e); }
       //---------------------------------------------------------------------------------------------------
       public event EventHandler<SocketEventArgs> closed;
       protected virtual void Closed(SocketEventArgs e) { if (closed != null) closed(this, e); }
       //---------------------------------------------------------------------------------------------------
       public event EventHandler<SocketEventArgs> ioError;
       protected virtual void IoError(SocketEventArgs e) { if (ioError != null) ioError(this, e); }
       //---------------------------------------------------------------------------------------------------
       public event EventHandler<SocketEventArgs> incomingData;
       protected virtual void IncomingData(SocketEventArgs e) { if (incomingData != null) incomingData(this, e); }
       //---------------------------------------------------------------------------------------------------
       public event EventHandler<SocketEventArgs> outgoingData;
       protected virtual void OutgoingData(SocketEventArgs e) { if (outgoingData != null) outgoingData(this, e); }
       //---------------------------------------------------------------------------------------------------
       public event EventHandler<SocketEventArgs> needNOP;
       protected virtual void NeedNOP(SocketEventArgs e) { if (needNOP != null) needNOP(this, e); }
       //---------------------------------------------------------------------------------------------------     
 
  /*  public delegate void EventHandler(SocketEventArgs e);
 
    public event EventHandler connected;
    public event EventHandler closed;
    public event EventHandler incomingData;
    public event EventHandler outgoingData;*/
 
    Socket socket;
    public string unpack ;
    UnpackChat unpackchat = new UnpackChat();
    UnpackGame unpackgame = new UnpackGame();
    public Thread _thread;
    public bool isConnected = false;
    object sync = new object();
    List<Action> actions = new List<Action>();  
 
    private void Start()
    {
        isConnected = false;
        unpack = "";
    }
 
    void Update(){
        lock(sync){ //обеспечиваем потокобезопасность чтения листа
            while(actions.Count!=0){ //и исполняем все действия
                actions[0].Invoke();
                actions.RemoveAt(0);
            }
        }
    }
 
    public void Execute(Action action){
        lock(sync){ //обеспечиваем потокобезопасность записи в лист
            actions.Add(action);
        }
        try{
            Thread.Sleep ();//усыпляем вызвавший поток
        }catch(ThreadInterruptedException){
        }finally{}
 
    }
 
    public void Connect(ServerObject serverObject)
    {
        try
        {
            unpack = serverObject.unpack; // Тип распаковки принятых данных 
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // Создаем Tcp socket
            IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse(serverObject.host), serverObject.port); // Создаем точку подключения 
            socket.ReceiveBufferSize = 65535; // Размер буфера сокета , куда приходят данные 
            socket.Connect(ipPoint); // Коннектимся 
            _thread = new Thread(ReceiveData);
            _thread.IsBackground = true;
            _thread.Start();
            isConnected = true;
            Connected(new SocketEventArgs("<Connected/>")); // Событие то-что законнектились 
        }
        catch (Exception e)
        {
            Debug.Log(e);
        }
    }
 
    public void Disconnect()
    {
        if (isConnected)
        {
            _thread.Interrupt();
            socket.Shutdown(SocketShutdown.Both); // Приостанавливаем прием/передачу   
            socket.Disconnect(true); // Отключаем сокет 
          //  socket.Close();
            //socket.Dispose();
            isConnected = false;
            Closed(new SocketEventArgs("<Disconnected/>")); // Событие дисконекта 
        }
    }
 
    public bool Status()
    {
            return isConnected;
    }
 
    public void SendData(string data) // Передача 
    {
        if (socket.Connected)
        {
            byte[] array = Encoding.UTF8.GetBytes(data + "\x00");
            socket.Send(array);
            Debug.Log("OUT : " + data);
            OutgoingData(new SocketEventArgs(data));
        }
    }
 
    public void ReceiveData() // Прием 
    {
        byte[] data = new byte[256]; // Размер буфера 
        int bytes = 0; // Кол-во считанных байт 
        string packet = ""; // Строка для хранения пакета 
        char stopChar = Convert.ToChar(0x00); // Конец пакета 
 
        while (socket.Connected)
        {
            while (socket.Available > 0)
            {
                bytes = socket.Receive(data, data.Length, SocketFlags.None);
                packet += Encoding.UTF8.GetString(data, 0, bytes);
            }
            if (packet.Length > 1)
            {
                if (packet[packet.Length - 1] == Convert.ToChar(0x00)) // Если у нас что - то есть и оно заканчивается на 0x00 
                {
                    packet = packet.Replace("\x0D" + "\x0A", "");
                    string[] packets = packet.Split(new char[] { stopChar }, StringSplitOptions.RemoveEmptyEntries);
 
                    //-------------------------------------------------------------------- а это запихиваем в Action List 
                    // И выполняем уже проверку и вызов события 
 
                    foreach (string s in packets) // перебираем пакеты 
                    {
                        switch (unpack)
                        {
 
                            case "GAME":
                                IncomingData(new SocketEventArgs(unpackgame.convert(s))); // вызов события 
                                break;
                            case "CHAT":
                                IncomingData(new SocketEventArgs(unpackchat.convert(s))); // вызов события 
                                break;
                            default:
                                IncomingData(new SocketEventArgs(s)); // вызов события 
                                break;
                        }
                    }
 
                    packet = ""; // Обнуляем 
                    }
                }
            }
        }
    }
Добавлено через 1 минуту
Надо будет покрутить и посмотреть что выйдет . Основной принцип я понял .

Добавлено через 4 часа 8 минут
Походу не прокатит в одном классе
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Collections.Generic;
using System.Threading;
using UnityEngine;
 
 
public class SocetConnect : MonoBehaviour
{
    //---------------------------------------------------------------------------------------------------
    public event EventHandler<SocketEventArgs> connected;
    protected virtual void Connected(SocketEventArgs e) { if (connected != null) connected(this, e); }
    //---------------------------------------------------------------------------------------------------
    public event EventHandler<SocketEventArgs> closed;
    protected virtual void Closed(SocketEventArgs e) { if (closed != null) closed(this, e); }
    //---------------------------------------------------------------------------------------------------
    public event EventHandler<SocketEventArgs> ioError;
    protected virtual void IoError(SocketEventArgs e) { if (ioError != null) ioError(this, e); }
    //---------------------------------------------------------------------------------------------------
    public event EventHandler<SocketEventArgs> incomingData;
    protected virtual void IncomingData(SocketEventArgs e) { if (incomingData != null) incomingData(this, e); }
    //---------------------------------------------------------------------------------------------------
    public event EventHandler<SocketEventArgs> outgoingData;
    protected virtual void OutgoingData(SocketEventArgs e) { if (outgoingData != null) outgoingData(this, e); }
    //---------------------------------------------------------------------------------------------------
    public event EventHandler<SocketEventArgs> needNOP;
    protected virtual void NeedNOP(SocketEventArgs e) { if (needNOP != null) needNOP(this, e); }
    //---------------------------------------------------------------------------------------------------
 
    Socket socket;
    public string unpack;
    UnpackChat unpackchat = new UnpackChat();
    UnpackGame unpackgame = new UnpackGame();
    public Thread _thread;
    public bool isConnected = false;
    object sync = new object();
    public List<Action> actions = new List<Action>();
 
    private void Start()
    {
        isConnected = false;
        unpack = "";
    }
 
    private void Update()
    {
        lock (sync)
        { //обеспечиваем потокобезопасность чтения листа
            while (actions.Count != 0)
            { //и исполняем все действия
                actions[0].Invoke();
                actions.RemoveAt(0);
            }
        }
    }
 
    public void Execute(Action action)
    {
        lock (sync)
        { //обеспечиваем потокобезопасность записи в лист
            actions.Add(action);
        }
        try
        {
            Thread.Sleep(100);//усыпляем вызвавший поток
        }
        catch (ThreadInterruptedException)
        {
        }
        finally { }
 
    }
 
    public void Connect(ServerObject serverObject)
    {
        try
        {
            unpack = serverObject.unpack; // Тип распаковки принятых данных 
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // Создаем Tcp socket
            IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse(serverObject.host), serverObject.port); // Создаем точку подключения 
            socket.ReceiveBufferSize = 65535; // Размер буфера сокета , куда приходят данные 
            socket.Connect(ipPoint); // Коннектимся 
            _thread = new Thread(ReceiveData);
            _thread.IsBackground = true;
            _thread.Start();
            isConnected = true;
            Connected(new SocketEventArgs("<Connected/>")); // Событие то-что законнектились 
        }
        catch (Exception e)
        {
            Debug.Log(e);
        }
    }
 
    public void Disconnect()
    {
        if (isConnected)
        {
            _thread.Interrupt();
            socket.Shutdown(SocketShutdown.Both); // Приостанавливаем прием/передачу   
            socket.Disconnect(true); // Отключаем сокет 
                                     //  socket.Close();
                                     //socket.Dispose();
            isConnected = false;
            Closed(new SocketEventArgs("<Disconnected/>")); // Событие дисконекта 
        }
    }
 
    public bool Status()
    {
        return isConnected;
    }
 
    public void SendData(string data) // Передача 
    {
        if (socket.Connected)
        {
            byte[] array = Encoding.UTF8.GetBytes(data + "\x00");
            socket.Send(array);
            Debug.Log("OUT : " + data);
            OutgoingData(new SocketEventArgs(data));
        }
    }
 
    public void transiver(string msg)
    {
        string[] packets = msg.Split(new char[] { Convert.ToChar(0x00) }, StringSplitOptions.RemoveEmptyEntries);
        foreach (string s in packets) // перебираем пакеты 
        {
            switch (unpack)
            {
 
                case "GAME":
                    IncomingData(new SocketEventArgs(unpackgame.convert(s))); // вызов события 
                    break;
                case "CHAT":
                    IncomingData(new SocketEventArgs(unpackchat.convert(s))); // вызов события 
                    break;
                default:
                    IncomingData(new SocketEventArgs(s)); // вызов события 
                    break;
            }
        }
    }
 
    public void ReceiveData() // Прием 
    {
        byte[] data = new byte[256]; // Размер буфера 
        int bytes = 0; // Кол-во считанных байт 
        string packet = ""; // Строка для хранения пакета 
        char stopChar = Convert.ToChar(0x00); // Конец пакета 
 
        while (socket.Connected)
        {
            while (socket.Available > 0)
            {
                bytes = socket.Receive(data, data.Length, SocketFlags.None);
                packet += Encoding.UTF8.GetString(data, 0, bytes);
            }
            if (packet.Length > 1)
            {
                if (packet[packet.Length - 1] == Convert.ToChar(0x00)) // Если у нас что - то есть и оно заканчивается на 0x00 
                {
                    packet = packet.Replace("\x0D" + "\x0A", "");
                    
                    Execute(() => { transiver(packet); }); //??????
 
 
                    packet = ""; // Обнуляем 
                }
            }
        }
    }
}
Добавлено через 23 часа 35 минут
Не оставляю надежду )))
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using UnityEngine;
 
 
 
public class SocetConnect // : MonoBehaviour
{
    public delegate void Task();
    public Queue<Task> TaskQueue = new Queue<Task>();
    public object _queueLock = new object();
 
    //---------------------------------------------------------------------------------------------------
    public event EventHandler<SocketEventArgs> connected;
    protected virtual void Connected(SocketEventArgs e) { if (connected != null) connected(this, e); }
    //---------------------------------------------------------------------------------------------------
    public event EventHandler<SocketEventArgs> closed;
    protected virtual void Closed(SocketEventArgs e) { if (closed != null) closed(this, e); }
    //---------------------------------------------------------------------------------------------------
    public event EventHandler<SocketEventArgs> ioError;
    protected virtual void IoError(SocketEventArgs e) { if (ioError != null) ioError(this, e); }
    //---------------------------------------------------------------------------------------------------
    public event EventHandler<SocketEventArgs> incomingData;
    protected virtual void IncomingData(SocketEventArgs e) { if (incomingData != null) incomingData(this, e); }
    //---------------------------------------------------------------------------------------------------
    public event EventHandler<SocketEventArgs> outgoingData;
    protected virtual void OutgoingData(SocketEventArgs e) { if (outgoingData != null) outgoingData(this, e); }
    //---------------------------------------------------------------------------------------------------
    public event EventHandler<SocketEventArgs> needNOP;
    protected virtual void NeedNOP(SocketEventArgs e) { if (needNOP != null) needNOP(this, e); }
    //---------------------------------------------------------------------------------------------------
 
    Socket socket;
    public string unpack;
    UnpackChat unpackchat = new UnpackChat();
    UnpackGame unpackgame = new UnpackGame();
    public Thread _thread;
    public bool isConnected = false;
 
 
    private void Start()
    {
        isConnected = false;
        unpack = "";
    }
 
    private void Update()
    {
        lock (_queueLock)
        {
            if (TaskQueue.Count > 0)
                Debug.Log("Что-то пришло"); // А до сюда не доходит 
            TaskQueue.Dequeue()();
        }
    }
 
 
    public void ScheduleTask(Task newTask)
    {
        Debug.Log("Пытаемся записать");
        lock (_queueLock)
        {
            if (TaskQueue.Count < 100)
                Debug.Log("Записали");
            TaskQueue.Enqueue(newTask);
            Debug.Log(TaskQueue.Count); // Выводит что кол-во в списке 1 
        }
    }
 
    public void Connect(ServerObject serverObject)
    {
        try
        {
            unpack = serverObject.unpack; // Тип распаковки принятых данных 
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // Создаем Tcp socket
            IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse(serverObject.host), serverObject.port); // Создаем точку подключения 
            socket.ReceiveBufferSize = 65535; // Размер буфера сокета , куда приходят данные 
            socket.Connect(ipPoint); // Коннектимся 
            _thread = new Thread(ReceiveData);
            _thread.IsBackground = true;
            _thread.Start();
            isConnected = true;
            Connected(new SocketEventArgs("<Connected/>")); // Событие то-что законнектились 
        }
        catch (Exception e)
        {
            Debug.Log(e);
        }
    }
 
    public void Disconnect()
    {
        if (isConnected)
        {
            _thread.Interrupt();
            socket.Shutdown(SocketShutdown.Both); // Приостанавливаем прием/передачу   
            socket.Disconnect(true); // Отключаем сокет 
                                     //  socket.Close();
                                     //socket.Dispose();
            isConnected = false;
            Closed(new SocketEventArgs("<Disconnected/>")); // Событие дисконекта 
        }
    }
 
    public bool Status()
    {
        return isConnected;
    }
 
    public void SendData(string data) // Передача 
    {
        if (socket.Connected)
        {
            byte[] array = Encoding.UTF8.GetBytes(data + "\x00");
            socket.Send(array);
            Debug.Log("OUT : " + data);
            OutgoingData(new SocketEventArgs(data));
        }
    }
 
    public void transiver(string msg)
    {
        string[] packets = msg.Split(new char[] { Convert.ToChar(0x00) }, StringSplitOptions.RemoveEmptyEntries);
        foreach (string s in packets) // перебираем пакеты 
        {
            switch (unpack)
            {
 
                case "GAME":
                    IncomingData(new SocketEventArgs(unpackgame.convert(s))); // вызов события 
                    break;
                case "CHAT":
                    IncomingData(new SocketEventArgs(unpackchat.convert(s))); // вызов события 
                    break;
                default:
                    IncomingData(new SocketEventArgs(s)); // вызов события 
                    break;
            }
        }
    }
 
    public void ReceiveData() // Прием 
    {
        byte[] data = new byte[256]; // Размер буфера 
        int bytes = 0; // Кол-во считанных байт 
        string packet = ""; // Строка для хранения пакета 
                            //  char stopChar = Convert.ToChar(0x00); // Конец пакета 
 
        while (socket.Connected)
        {
            while (socket.Available > 0)
            {
                bytes = socket.Receive(data, data.Length, SocketFlags.None);
                packet += Encoding.UTF8.GetString(data, 0, bytes);
            }
            if (packet.Length > 1)
            {
                if (packet[packet.Length - 1] == Convert.ToChar(0x00)) // Если у нас что - то есть и оно заканчивается на 0x00 
                {
                    packet = packet.Replace("\x0D" + "\x0A", "");
 
                    //    Execute(new Action () => { transiver(packet); }); //??????
 
                    //      Action act = () => { transiver(packet); };
                    //       Execute(act); //??????
 
                        ScheduleTask(new Task(delegate { transiver(packet); }));
                    //transiver(packet);
                    packet = ""; // Обнуляем 
                }
            }
        }
    }
}
В Update не запускает ?
0
753 / 600 / 204
Регистрация: 06.08.2015
Сообщений: 2,432
16.04.2018, 09:21 15
Апдейты вызываются только из монобеха
0
2 / 2 / 1
Регистрация: 09.01.2015
Сообщений: 382
17.04.2018, 01:01  [ТС] 16
Цитата Сообщение от Cr0c Посмотреть сообщение
Апдейты вызываются только из монобеха
У меня раскоменчен Моно . Но Update не запускается . Для проверки в апдайт записал дебаг . но походу апдате не включается . Может надо не как класс запускать ?
C#
1
SocetConnect my_sock = new SocetConnect();
а так вот что я в Update запихнул
C#
1
2
3
4
5
6
7
8
9
10
11
    void Update()
    {
        Debug.Log("Update");
 
        lock (_queueLock)
        {
            if (TaskQueue.Count > 0)
                Debug.Log("Что-то пришло"); // А до сюда не доходит 
            TaskQueue.Dequeue()();
        }
    }
Добавлено через 22 минуты
Ну объявил я так
C#
1
my_sock = gameObject.AddComponent<SocetConnect>();
Update заработал но вылезла ошибка :

InvalidOperationException: Operation is not valid due to the current state of the object
System.Collections.Generic.Queue`1[SocetConnect+Task].Peek ()
System.Collections.Generic.Queue`1[SocetConnect+Task].Dequeue ()
SocetConnect.Update () (at Assets/Scripts/net/SocetConnect.cs:62)

Добавлено через 1 час 22 минуты
Вот так заработало . Но теперь косяк в том что при запуске приложения ЦП грузится до 100% .
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Collections;
using System.Threading;
using UnityEngine.UI;
using System.Collections.Generic;
using UnityEngine;
 
public class SocetConnect : MonoBehaviour
{
 
    public delegate void Task();
    public Queue<Task> TaskQueue;
    public object _queueLock;
 
    //---------------------------------------------------------------------------------------------------
    public event EventHandler<SocketEventArgs> connected;
    protected virtual void Connected(SocketEventArgs e) { if (connected != null) connected(this, e); }
    //---------------------------------------------------------------------------------------------------
    public event EventHandler<SocketEventArgs> closed;
    protected virtual void Closed(SocketEventArgs e) { if (closed != null) closed(this, e); }
    //---------------------------------------------------------------------------------------------------
    public event EventHandler<SocketEventArgs> ioError;
    protected virtual void IoError(SocketEventArgs e) { if (ioError != null) ioError(this, e); }
    //---------------------------------------------------------------------------------------------------
    public event EventHandler<SocketEventArgs> incomingData;
    protected virtual void IncomingData(SocketEventArgs e) { if (incomingData != null) incomingData(this, e); }
    //---------------------------------------------------------------------------------------------------
    public event EventHandler<SocketEventArgs> outgoingData;
    protected virtual void OutgoingData(SocketEventArgs e) { if (outgoingData != null) outgoingData(this, e); }
    //---------------------------------------------------------------------------------------------------
    public event EventHandler<SocketEventArgs> needNOP;
    protected virtual void NeedNOP(SocketEventArgs e) { if (needNOP != null) needNOP(this, e); }
    //---------------------------------------------------------------------------------------------------
 
    Socket socket;
    public string unpacket = "null";
    UnpackChat unpackchat;
    UnpackGame unpackgame;
    public Thread _thread;
    public bool isConnected;
    object sync = new object();
    public List<Action> actions = new List<Action>();
 
 
    void Start()
    {
        _queueLock = new object();
        TaskQueue = new Queue<Task>();
        isConnected = false;
        unpackgame = new UnpackGame();
        unpackchat = new UnpackChat();
    }
 
    private void Update()
    {
        lock (sync)
        { //обеспечиваем потокобезопасность чтения листа
            while (actions.Count != 0)
            { //и исполняем все действия
                actions[0].Invoke();
                actions.RemoveAt(0);
            }
        }
    }
 
    public void Execute(Action action)
    {
        lock (sync)
        { //обеспечиваем потокобезопасность записи в лист
            actions.Add(action);
        }
        try
        {
            Thread.Sleep(100);//усыпляем вызвавший поток
        }
        catch (ThreadInterruptedException)
        {
        }
        finally { }
 
    }
 
    public void Connect(ServerObject serverObject)
    {
        try
        {
            this.unpacket = serverObject.unpack; // Тип распаковки принятых данных 
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // Создаем Tcp socket
            IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse(serverObject.host), serverObject.port); // Создаем точку подключения 
            socket.ReceiveBufferSize = 65535; // Размер буфера сокета , куда приходят данные 
            socket.Connect(ipPoint); // Коннектимся 
            _thread = new Thread(ReceiveData);
            _thread.IsBackground = true;
            _thread.Start();
            isConnected = true;
            Connected(new SocketEventArgs("<Connected/>")); // Событие то-что законнектились 
        }
        catch (Exception e)
        {
            Debug.Log(e);
        }
    }
 
    public void Disconnect()
    {
        if (isConnected)
        {
            _thread.Interrupt();
            socket.Shutdown(SocketShutdown.Both); // Приостанавливаем прием/передачу   
            socket.Disconnect(true); // Отключаем сокет 
                                     //  socket.Close();
                                     //socket.Dispose();
            isConnected = false;
            Closed(new SocketEventArgs("<Disconnected/>")); // Событие дисконекта 
        }
    }
 
    public bool Status()
    {
        return isConnected;
    }
 
    public void SendData(string data) // Передача 
    {
        if (socket.Connected)
        {
            byte[] array = Encoding.UTF8.GetBytes(data + "\x00");
            socket.Send(array);
            Debug.Log("OUT : " + data);
            OutgoingData(new SocketEventArgs(data));
        }
    }
 
    public void transiver(string msg)
    {
        string[] packets = msg.Split(new char[] { Convert.ToChar(0x00) }, StringSplitOptions.RemoveEmptyEntries);
        foreach (string s in packets) // перебираем пакеты 
        {
            switch (this.unpacket)
            {
 
                case "GAME":
                    IncomingData(new SocketEventArgs(unpackgame.convert(s))); // вызов события 
                    break;
                case "CHAT":
                    string[] p = s.Split(new char[] { Convert.ToChar(0x0D), Convert.ToChar(0x0A) }, StringSplitOptions.RemoveEmptyEntries);
                    foreach (string s0 in p) 
                    {
                        IncomingData(new SocketEventArgs(unpackchat.convert(s0))); // вызов события 
                    }
                    break;
                default:
                    IncomingData(new SocketEventArgs(s)); // вызов события 
                    break;
            }
        }
    }
 
    public void ReceiveData() // Прием 
    {
        byte[] data = new byte[256]; // Размер буфера 
        int bytes = 0; // Кол-во считанных байт 
        string packet = ""; // Строка для хранения пакета 
                            //  char stopChar = Convert.ToChar(0x00); // Конец пакета 
 
        while (socket.Connected)
        {
            while (socket.Available > 0)
            {
                bytes = socket.Receive(data, data.Length, SocketFlags.None);
                packet += Encoding.UTF8.GetString(data, 0, bytes);
            }
            if (packet.Length > 1)
            {
                if (packet[packet.Length - 1] == Convert.ToChar(0x00)) // Если у нас что - то есть и оно заканчивается на 0x00 
                {
                    packet = packet.Replace("\x0D" + "\x0A", "");
 
                    Execute(() => { transiver(packet); });
 
                    packet = ""; // Обнуляем 
                }
            }
        }
    }
}
0
753 / 600 / 204
Регистрация: 06.08.2015
Сообщений: 2,432
17.04.2018, 10:53 17
Marchcat, профайлер на кого показывает?
0
2 / 2 / 1
Регистрация: 09.01.2015
Сообщений: 382
17.04.2018, 19:01  [ТС] 18
А про него то я и забыл вчера . Сейчас на работе . Я вчера убрал в заголовок
C#
1
game_sock = gameObject.AddComponent<SocetConnect>();
При реконекте давил на все 100% . Сейчас опустил до 60% .

Добавлено через 2 часа 47 минут
Мне кажется что проблема в том что сокеты не уничтожаются.
У меня получается так что когда на сцене щелкаю вход . С начало конектимся к серверу который нам выдает список серверов . Потом надо его закрыть . После коннектимся по списку . Если персонаж не на этом сервере . то реконект . Как только находим нужный сервер . Логинимся и получаем данные о персонаже . После подключаем сокет Чата .
0
2 / 2 / 1
Регистрация: 09.01.2015
Сообщений: 382
17.04.2018, 21:46  [ТС] 19
Раскидал сокеты . но все равно показывает загрузку ЦП 60%
Миниатюры
Многопоточный сокет и Создание объектов в Unity  
0
753 / 600 / 204
Регистрация: 06.08.2015
Сообщений: 2,432
18.04.2018, 08:43 20
Marchcat, где это видно? Там 70% оверхед едитора.
0
18.04.2018, 08:43
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
18.04.2018, 08:43
Помогаю со студенческими работами здесь

Всплывающие подсказки для объектов unity c#
Доброго времени суток. Предупреждаю сразу, в Unity я новичок, так что... Нужно создать...

Стрельба из оружия, пулинг объектов в unity
Нужно ли реализовывать стрельбу из оружия через пулинг? Например, есть карта на которой несколько...

Большие масштабы объектов. Планеты на Unity 5
Здравствуйте, недавно написал скрипт на смещение мира каждые 1000 юнитов и возвращая игрока в центр...

Уничтожение объектов через другие объекты. Unity. C#
Я в тупике Сверху вниз из пяти точек спавна рандомно падают префабы, пусть будет картошка....


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru