Консультация по проекту + необычная проблема tcpclient
Привет
Я работаю над созданием сервера для игры, которую собираюсь начать разрабатывать с использованием Unreal Engine, однако я хочу, чтобы сервер был приложением WinForms. Мой подход состоял в том, чтобы создать приложение C# WinForms, которое способно принимать TCP-соединения и хранить их, получать пакеты от любого и транслировать при необходимости. Примером может служить PacketPlayerDisconnect, когда игрок отключается от сервера, этот пакет отправляется всем другим клиентам и содержит идентификатор игрока, так что модель игрока удаляется на клиентах.
Прежде всего я хотел бы знать, является ли это лучшим подходом или нет, и если у вас есть какие-либо советы.
EDIT: в моем решении решается следующее
Способ реализации пакетной системы в моем коде заключается в отправке массива байтов в следующем формате:
0 | 1 | 2...
длина данных | packetID | содержимое пакета...
Байты 1 и 2 позволяют мне построить правильный пакет и заполнить его содержимое, когда он будет получен.
Я вижу странную проблему, когда сервер отправляет один пакет клиенту, и он говорит, что получает 7. Вот код:
Сервер:
public class GameServer { private Main main; private List<GameClient> clients = new List<GameClient>(); #region Config private int port = 1123; #endregion #region Connection private TcpListener listener; private bool listening = false; private Thread listenThread; #endregion public GameServer(Main main) { this.main = main; } public void start() { listener = new TcpListener(IPAddress.Parse("127.0.0.1"), port); listener.Start(); listenThread = new Thread(listen); listenThread.Start(); } public void stop() { listening = false; listener.Server.Close(); listener.Stop(); clients.ForEach((client) => client.disconnect()); } private void listen() { listening = true; while(listening) { TcpClient client = listener.AcceptTcpClient(); GameClient game_client = new GameClient(main, client); clients.Add(game_client); game_client.sendPacket(new PacketRawData("Hello, Client")); } }
Клиент:
public class GameClient { private Main main; private TcpClient client; private NetworkStream client_stream; private Thread listenThread; private bool listening; public GameClient(Main main, String ipAddress, int portNum) { this.main = main; client = new TcpClient(); listenThread = new Thread(receive); listenThread.Start(); client.Connect(ipAddress, portNum); client_stream = client.GetStream(); } public void send(string message) { byte[] message_data = Encoding.UTF8.GetBytes(message); byte[] data = new byte[1 + message_data.Length]; int message_length = message_data.Length; data[0] = (byte)message_length; for(int i = 0; i < message_length; i++) // place message bytes after length byte { data[i + 1] = message_data[1]; } NetworkStream client_stream = client.GetStream(); client_stream.Write(data, 0, data.Length); client_stream.Flush(); main.logPacket(PacketDirection.SEND, message); } private void receive() { listening = true; while(listening) { if(client_stream.DataAvailable) { byte[] length_byte = new byte[1]; client_stream.Read(length_byte, 0, length_byte.Length); // read first byte (length) int data_length = length_byte[0]; byte[] data_bytes = new byte[data_length]; // read rest of data client_stream.Read(length_byte, 0, length_byte.Length); String data = Encoding.UTF8.GetString(data_bytes); main.logPacket(PacketDirection.RECEIVE, data); } } } }
Что я уже пробовал:
Использование Wireshark для мониторинга пакетов, но он не обнаруживает мои интерфейсы
Использование нескольких методов для отправки/получения.
________________
Когда вы устанете от низкоуровневых проблем, взгляните на WCF (https://www.codeproject.com/Articles/406096/A-beginners-tutorial-for-understanding-Windows)
технология...
Если вы разрабатываете оба - клиент и сервер - я не вижу никаких причин использовать примитивные сокеты.