客户端只收到一些数据包

时间:2018-12-16 18:57:03

标签: c# sockets unity3d

我在学习网络游戏,但是确实有一些问题。现在我的代码由于学习和尝试自己调试而非常混乱,但是我没有主意。

发生的事情是,当人们登录时,它应该向所有连接的人发送一个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";
        }
    }
}

0 个答案:

没有答案