Клиент получает только некоторые пакеты - PullRequest
0 голосов
/ 16 декабря 2018

Я играю в изучение сетей, но у меня есть некоторые проблемы.Теперь мой код довольно запутанный от изучения и попыток отладить его сам, однако у меня нет идей.

То, что происходит, когда люди входят в систему, должны отправлять SyncPacket всем подключенным, чтобы мы могли отправлять позиции игрокови т. д.

Игрок, который подключается последним, может видеть всех игроков, но он не обновляется для всех только при подключении.

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

Код выглядит следующим образом:

Сервер:

using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Threading;
using System.Net;
using ServerData;

namespace Server
{
    class Server
    {
        static Socket listenerSocket;
        static List<ClientData> _clients;

        static void Main(string[] args)
        {
            listenerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            _clients = new List<ClientData>();

            IPAddress ip = IPAddress.Parse(Packet.GetIp4Adress());
            IPEndPoint ipEnd = new IPEndPoint(ip, 1337);

            Console.WriteLine("Starting server on:" + Packet.GetIp4Adress());
            listenerSocket.Bind(ipEnd);

            Thread listenerThread = new Thread(ListenThread);
            listenerThread.Start();
        }

        static void ListenThread()
        {
            for (; ; )
            {
                listenerSocket.Listen(0);

                ClientData client = new ClientData(listenerSocket.Accept());
                _clients.Add(client);
                client.SendRegistrationPacket();
            }
        }

        public static void Data_IN(object cSocket)
        {
            Socket clientSocket = (Socket)cSocket;

            byte[] buffer;
            int readBytes = 0;

            for (; ; )
            {
                try
                {
                    buffer = new byte[clientSocket.SendBufferSize];
                    readBytes = clientSocket.Receive(buffer);

                    if (readBytes > 0)
                    {
                        Packet p = new Packet(buffer);
                        DataManager(p);
                    }
                }
                catch (SocketException ex)
                {
                    foreach (ClientData c in _clients)
                    {
                        if (!c.clientSocket.Connected)
                        {
                            c.clientSocket.Close();
                            _clients.Remove(c);
                        }
                    }
                }
            }
        }

        public static void DataManager(Packet p)
        {

            if (p.packetType != PacketType.PlayerPositionUpdate)
            {
                Console.WriteLine("::> " + p.packetType);
            }

            switch (p.packetType)
            {
                case PacketType.PlayerRegistration:
                    Packet playersUpdate = new Packet(PacketType.SyncAllPlayers, "server");

                    foreach (ClientData c in _clients)
                    {
                        string gDataStr = c.ID + ",";
                        gDataStr += c.name + ",";
                        gDataStr += c.x + ",";
                        gDataStr += c.y;

                        playersUpdate.gData.Add(gDataStr);
                    }

                    for (int i = 0; i < _clients.Count; i++)
                    {
                        _clients[i].clientSocket.Send(playersUpdate.toBytes());
                    }
                    break;

                case PacketType.PlayerShootingRequest:

                    int clickX = int.Parse(p.gData[0]);
                    int clickY = int.Parse(p.gData[1]);

                    int Index = _clients.FindIndex(i => i.ID == p.senderID);
                    _clients[Index].ammo--;
                    Packet ShooterStatUpdate = new Packet(PacketType.PlayerStatUpdate, "server", _clients[Index].ammo.ToString());
                    SendTo(p.senderID, ShooterStatUpdate);

                    foreach (ClientData c in _clients)
                    {
                        float top = c.y + (float.Parse(p.gData[3]) / 2f);
                        float btm = c.y - (float.Parse(p.gData[3]) / 2f);
                        float left = c.x - (float.Parse(p.gData[2]) / 2f);
                        float right = c.x + (float.Parse(p.gData[2]) / 2f);

                        int chkSum = 0;
                        chkSum = clickY <= top ? 1 : 0;
                        chkSum = clickY >= btm ? 1 : 0;
                        chkSum = clickX >= left ? 1 : 0;
                        chkSum = clickX <= right ? 1 : 0;

                        if (chkSum == 4)
                        {
                            Index = _clients.FindIndex(j => j == c);
                            _clients[Index].health -= 7;
                            Packet ShotStatUpdate = new Packet(PacketType.PlayerStatUpdate, "server", _clients[Index].health.ToString());
                            SendTo(_clients[Index].ID, ShotStatUpdate);

                            break;
                        }
                    }

                    break;
                case PacketType.PlayerPositionUpdate:
                    float x = float.Parse(p.gData[0]);
                    float y = float.Parse(p.gData[1]);

                    _clients.Find(c => c.ID == p.senderID).x = x;
                    _clients.Find(c => c.ID == p.senderID).y = y;

                    SendToAll(p);
                    break;

                case PacketType.PlayerVisualUpdate:
                    SendToAllExpect(p.senderID, p);
                    break;
            }
        }

        public static void SendTo(string ID, Packet p)
        {
            Console.WriteLine("<:: " + p.packetType + ", " + ID);
            _clients.Find(x => x.ID == ID).clientSocket.Send(p.toBytes());
        }

        public static void SendToAllExpect(string ID, Packet p)
        {
            Console.WriteLine("<:: " + p.packetType + " -Execpt");

            foreach (ClientData c in _clients)
            {
                if (c.ID != ID)
                {
                    c.clientSocket.Send(p.toBytes());
                }
            }
        }
        public static void SendToAll(Packet p)
        {
            foreach (ClientData c in _clients)
            {
                SendTo(c.ID, p);
            }
        }
    }

    class ClientData
    {
        public Thread clientThread;
        public Socket clientSocket;

        public string ID;

        public string name;
        public float x;
        public float y;
        public int health;
        public int ammo;
        public float gunRotation;

        //??? - TODO: figure out animation values?

        public ClientData()
        {
            ID = Guid.NewGuid().ToString();
            clientThread = new Thread(Server.Data_IN);
            clientThread.Start(clientSocket);
        }
        public ClientData(Socket _clientSocket)
        {
            ID = Guid.NewGuid().ToString();
            clientSocket = _clientSocket;
            clientThread = new Thread(Server.Data_IN);
            clientThread.Start(clientSocket);
        }

        public void SendRegistrationPacket()
        {
            Packet p = new Packet(PacketType.PlayerRegistration, "server", ID);
            clientSocket.Send(p.toBytes());
        }
    }
}

Клиент:

using System.Net;
using System.Net.Sockets;
using UnityEngine;
using ServerData;
using System;
using System.Threading;
using System.Collections.Generic;

public class MPplayer
{
    public string ID;

    public float x, y;
    public float gunRot;
    public int state;
    public GameObject character;

    public Vector2 lastPos;

    public MPplayer(string _ID, float _x, float _y)
    {
        ID = _ID;
        x = _x;
        y = _y;
        state = 0;
    }

    public void Update()
    {
        character.transform.position = new Vector2(x, y);
    }
}

public class Client : MonoBehaviour
{
    public Socket master;
    public string name;
    public string ID;
    public UIHandler uihandler;
    public IPAddress ip;
    public bool isInit;

    private Packet lastMsg;
    private Packet currMsg;

    public List<MPplayer> players;

    public float health { get; set; }
    public float ammo { get; set; }
    public CharacterController cc;
    public GameObject prefab;
    public Vector2 lastPos;

    private void Awake()
    {
        uihandler = GetComponent<UIHandler>();
        players = new List<MPplayer>();
        Application.runInBackground = true;
        DontDestroyOnLoad(this);
    }

    private void Update()
    {
        if (uihandler.state == 0)
        {
            name = uihandler.clientName;
        }
        else if (uihandler.state == 2)
        {
            ip = IPAddress.Parse(uihandler.ip);
            master = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            IPEndPoint ipEnd = new IPEndPoint(ip, 1337);

            try
            {
                Debug.Log("connecting");
                master.Connect(ipEnd);

                uihandler.state = 3;
            }
            catch (SocketException ex)
            {
                uihandler.state = 0;
                Debug.LogError("Error with connection:");
                Debug.Log(ex.ToString());
            }
        }
        else if(uihandler.state == 3)
        {
            if (!isInit)
            {
                Thread data_in = new Thread(Data_IN);
                data_in.Start();
                isInit = true;
            }

            if(lastMsg != currMsg)
            {
                DataManager(currMsg);
                lastMsg = currMsg;

            }
        }
        else if(uihandler.state == 4)
        {
            float speed = 5;

            float vSpeed = Input.GetAxis("Vertical") * Time.deltaTime * speed;
            float hSpeed = Input.GetAxis("Horizontal") * Time.deltaTime * speed;

            players.Find(x => x.ID == this.ID).character.transform.Translate(hSpeed, vSpeed, 0);
            Vector3 currPos = players.Find(x => x.ID == this.ID).character.transform.position;

            if (lastPos != new Vector2(currPos.x, currPos.y))
            {
                lastPos = new Vector2(currPos.x, currPos.y);
                Packet packet = new Packet(PacketType.PlayerPositionUpdate, ID, currPos.x.ToString(), currPos.y.ToString());
                master.Send(packet.toBytes());
            }

            uihandler.stats.text = "Health: " + health + "\n" + "Ammo: " + ammo;
        }
    }

    private void Data_IN()
    {
        byte[] buffer;
        int readBytes;

        for (; ; )
        {
            try
            {
                buffer = new byte[master.SendBufferSize];
                readBytes = master.Receive(buffer);

                if (readBytes > 0)
                {
                    currMsg = new Packet(buffer);
                }
            }
            catch (SocketException ex)
            {
                //TODO: jump over gracefully!
                Debug.Log("The server has disconnected");
                throw;
            }
        }
    }

    private void DataManager(Packet p)
    {
        Debug.Log("::>" + p.packetType);
        switch (p.packetType)
        {
            case PacketType.SyncAllPlayers:

                Debug.Log("Hey");
                foreach (string s in p.gData)
                {
                    string[] data = s.Split(',');

                    float sX = float.Parse(data[2]);
                    float sY = float.Parse(data[3]);

                    int ind = players.FindIndex(x => x.ID == data[0]);

                    if (ind >= 0)
                    {
                        players[ind].x = sX;
                        players[ind].y = sY;
                    }
                    else
                    {
                        MPplayer mPplayer = new MPplayer(data[0], sX, sY);

                        GameObject mpPrefab = Instantiate(prefab);
                        mpPrefab.transform.position = new Vector2(sX, sY);

                        mPplayer.character = mpPrefab;
                        players.Add(mPplayer);

                        Debug.Log("Adding Player: " + mPplayer.ID);
                    }

                    lastPos = data[0] == this.ID ? new Vector2(sX, sY) : lastPos;

                    uihandler.state = 4;
                }
                break;

            case PacketType.PlayerRegistration:
                this.ID = p.gData[0];

                Packet packet = new Packet(PacketType.PlayerRegistration, this.ID);
                master.Send(packet.toBytes());
                break;

            case PacketType.PlayerPositionUpdate:
                int Index = players.FindIndex(i => i.ID == p.senderID);

                float px = float.Parse(p.gData[0]);
                float py = float.Parse(p.gData[1]);

                players[Index].x = px;
                players[Index].y = py;

                players[Index].Update();
                break;

            case PacketType.PlayerStatUpdate:
                if(p.gData[0] == this.ID)
                {
                    health = float.Parse(p.gData[1]);
                    ammo = float.Parse(p.gData[2]);
                }

                break;

            case PacketType.PlayerVisualUpdate:
                int index = players.FindIndex(i => i.ID == p.gData[0]);
                players[index].gunRot = float.Parse(p.gData[1]);

                break;

            default:
                break;
        }
    }
}

Данные сервера:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Runtime.Serialization.Formatters.Binary;
using UnityEngine;

namespace ServerData
{
    public enum PacketType
    {
        PlayerRegistration,
        PlayerJoined,
        PlayerShootingRequest,
        PlayerPositionUpdate,
        PlayerStatUpdate,
        PlayerVisualUpdate,
        SyncAllPlayers,
    }

    [Serializable]
    public class Packet
    {
        public string senderID;
        public PacketType packetType;

        public List<string> gData;
        public int packetInt;
        public bool packetBool;

        public Packet(PacketType _type, string _senderID, params object[] data)
        {
            gData = new List<string>();
            for (int i = 0; i < data.Length; i++)
            {
                gData.Add(data[i].ToString());
            }

            senderID = _senderID;
            packetType = _type;
        }

        public Packet(byte[] bytes)
        {
            gData = new List<string>();

            MemoryStream ms = new MemoryStream(bytes);
            BinaryReader br = new BinaryReader(ms);

            this.packetType = (PacketType)br.ReadInt32();

            this.senderID = br.ReadString();

            this.packetInt = br.ReadInt32();
            this.packetBool = br.ReadBoolean();

            int count = br.ReadInt32();

            for (int i = 0; i < count; i++)
            {
                gData.Add(br.ReadString());
            }

            br.Close();
            ms.Close();
        }

        public byte[] toBytes()
        {
            byte[] bytes;

            using (MemoryStream ms = new MemoryStream())
            {
                using (BinaryWriter bw = new BinaryWriter(ms))
                {
                    bw.Write((int)packetType);
                    bw.Write(senderID);

                    bw.Write(packetInt);
                    bw.Write(packetBool);
                    bw.Write(gData.Count);

                    for (int i = 0; i < gData.Count; i++)
                    {
                        bw.Write(gData[i]);
                    }

                    bw.Close();
                }

                ms.Flush();
                bytes = ms.GetBuffer();
                ms.Close();
            }

            return bytes;
        }

        public static string GetIp4Adress()
        {
            IPAddress[] ips = Dns.GetHostAddresses(Dns.GetHostName());

            foreach (IPAddress ip in ips)
            {
                if (ip.AddressFamily == AddressFamily.InterNetwork)
                {
                    return ip.ToString();
                }
            }

            return "127.0.0.1";
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...