Сокеты. Непонятные сообщения и странные выводы

У меня есть некий удалённый сервер с таким кодом:

using System;
using System.Collections;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace SkyJumpServer
{
    enum Message
    {
        JOINED, LOADED, OUTED, MOVED, DATA, VOTE, START
    }

    enum GameState
    {
        GAME, LOBBY
    }

    class Server
    {
        private static Socket socket;

        private static Hashtable clients = new Hashtable();

        public static Hashtable clientsData = new Hashtable();

        private static GameState gameState;

        private static Hashtable votes;

        static void Main(string[] args)
        {
            IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 40001);

            socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            socket.Bind(ipPoint);

            socket.Listen(10);

            while (true)
            {
                Socket client = socket.Accept();

                String ip = client.RemoteEndPoint.ToString();

                SendMessage(Message.JOINED, null, null, ip, "ALL");

                clients.Add(ip, client);

                new Thread(new ParameterizedThreadStart(ListenClient)).Start(client);
            }
        }

        public static void ListenClient(object c)
        {
            Socket client = (Socket) c;

            String ip = client.RemoteEndPoint.ToString();

            foreach (DictionaryEntry pair in clientsData)
            {
                client.Send(Encoding.UTF8.GetBytes((char[]) pair.Key));
                client.Send(BitConverter.GetBytes((int) pair.Value));
            }

            client.Send(Encoding.UTF8.GetBytes("END"));


            int id = 0;

            Message msg = Message.MOVED;
            byte[] lArg = null;
            byte[] rArg = null;
            String recipient = null;

            while (!(client.Poll(0, SelectMode.SelectRead) && client.Available == 0))
            {
                id++;

                if (id == 4)
                {
                    id = 0;

                    Console.WriteLine(msg);
                    Console.WriteLine(lArg);
                    Console.WriteLine(rArg);
                    Console.WriteLine(ip);
                    Console.WriteLine(recipient);

                    SendMessage(msg, lArg, rArg, ip, recipient);
                }

                byte[] buffer = new byte[client.Available];

                client.Receive(buffer);

                switch (id) {
                    case 0:
                        msg = (Message) Enum.Parse(typeof(Message), Encoding.UTF8.GetString(buffer));
                        break;
                    case 1:
                        lArg = buffer;
                        break;
                    case 2:
                        rArg = buffer;
                        break;
                    case 3:
                        recipient = Encoding.UTF8.GetString(buffer);
                        break;
                }
            }

            clients.Remove(ip);

            client.Shutdown(SocketShutdown.Both);
            client.Close();

            SendMessage(Message.OUTED, null, null, ip, "ALL");
        }

        public static void SendMessage(Message message, byte[] lArg, byte[] rArg, String sender, String recipient)
        {
            lArg = lArg is null ? new byte[0] : lArg;
            rArg = rArg is null ? new byte[0] : rArg;

            if (recipient == "SERVER")
                ReceiveMessage(message, lArg, rArg, sender);
            else if (recipient == "ALL")
                foreach (DictionaryEntry pair in clients)
                {
                    Socket client = (Socket)pair.Value;

                    client.Send(Encoding.UTF8.GetBytes(message.ToString()));

                    client.Send(lArg);
                    client.Send(rArg);

                    client.Send(Encoding.UTF8.GetBytes(sender));
                }
            else
            {
                Socket client = (Socket) clients[recipient];

                client.Send(Encoding.UTF8.GetBytes(message.ToString()));
                
                client.Send(lArg);
                client.Send(rArg);
                
                client.Send(Encoding.UTF8.GetBytes(sender));
            }
        }

        public static void ReceiveMessage(Message message, byte[] lArg, byte[] rArg, string sender)
        {
            switch (message)
            {
                case Message.DATA:
                    clientsData.Add(sender, BitConverter.ToInt32(lArg));
                    break;
                case Message.VOTE:
                    if (gameState == GameState.LOBBY)
                    {
                        int id = BitConverter.ToInt32(lArg);

                        if (votes.Contains(id))
                            votes.Add(id, ((int) votes[id]) + 1);
                        else
                            votes.Add(id, 1);
                    }

                    break;
            }
        }

        public static void GameThread()
        {
            gameState = GameState.LOBBY;

            int timeRemaining = 15;

            while (timeRemaining > 0) {
                if (clients.Count < 2)
                    continue;

                Thread.Sleep(1000);
                timeRemaining--;
            }


            gameState = GameState.GAME;

            DictionaryEntry max;

            foreach (DictionaryEntry pair in votes)
                if ((object) max is null || (int) pair.Value > (int) max.Value)
                    max = pair;

            votes.Clear();


            SendMessage(Message.START, BitConverter.GetBytes((int) max.Key), null, "SERVER", "ALL");
        }
    }
}

И Unity клиент:

using System;
using System.Collections;
using System.Net;
using System.Net.Sockets;
using System.Runtime.CompilerServices;
using System.Text;
using UnityEngine;

public class RoomConnector : MonoBehaviour
{
    public static RoomConnector instance;

    public Transform OtherPlayer;

    private static Socket socket;
    private static IPEndPoint ipPoint;

    public static Hashtable playersData = new Hashtable();

    private int id = 0;
    private Message msg = Message.MOVED;
    private byte[] lArg = null;
    private byte[] rArg = null;
    private String sender = null;

    public enum Message
    {
        JOINED, OUTED, MOVED, DATA, VOTE, START
    }

    private void Awake()
    {
        ipPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 40001);

        socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    }

    private void Start()
    {
        if (instance == null)
            instance = this;

        if (GameObject.Find("Player") != null)
            LoadRoom();
    }

    private void OnDestroy()
    {
        socket.Close();
    }

    public static void Connect() {
        socket.Connect(ipPoint);

        int id = 0;

        String ip = "";
        int skin = 0;

        while (true)
        {
            if (id == 1)
            {
                id = -1;

                playersData[ip] = skin;
            }

            if (socket.Available == 0)
                continue;

            id++;

            byte[] buffer = new byte[socket.Available];

            socket.Receive(buffer);

            foreach (byte b in buffer)
                Debug.Log(b);

            if (Encoding.UTF8.GetString(buffer) == "END")
                break;

            switch (id)
            {
                case 0:
                    ip = Encoding.UTF8.GetString(buffer);
                    break;
                case 1:
                    skin = BitConverter.ToInt32(buffer, 0);
                    break;
            }
        }

        SendMessage(Message.DATA, BitConverter.GetBytes(PlayerPrefs.GetInt("CurrentSkin")), null, "SERVER");
    }

    public static void LoadRoom()
    {
        foreach (DictionaryEntry pair in playersData) {
            String ip = (String) pair.Key;
            int skin = (int) pair.Value;

            Transform otherPlayer = Instantiate(instance.OtherPlayer, new Vector3(0f, -3f, -1f), Quaternion.identity);
            otherPlayer.name = ip;
            otherPlayer.GetComponent<SpriteRenderer>().sprite = ChangeSkin.sprites[skin];
        }
    }

    void Update()
    {
        if (!socket.Connected)
            return;

        GameObject player = GameObject.Find("Player");

        if (player != null)
            SendMessage(Message.MOVED, BitConverter.GetBytes(player.transform.position.x), BitConverter.GetBytes(player.transform.position.y), "ALL");

        if (id == 3)
        {
            id = -1;

            ReceiveMessage(msg, lArg, rArg, sender);
        }

        if (socket.Available == 0)
            return;

        id++;

        byte[] buffer = new byte[socket.Available];

        socket.Receive(buffer);

        switch (id)
        {
            case 0:
                msg = (Message)Enum.Parse(typeof(Message), Encoding.UTF8.GetString(buffer));
                break;
            case 1:
                lArg = buffer;
                break;
            case 2:
                rArg = buffer;
                break;
            case 3:
                sender = Encoding.UTF8.GetString(buffer);
                break;
        }
    }

    [MethodImpl(MethodImplOptions.Synchronized)]
    public static void SendMessage(Message message, byte[] lArg, byte[] rArg, String recipient)
    {
        Debug.Log("START");
        Debug.Log(message);

        lArg = lArg is null ? new byte[0] : lArg;
        rArg = rArg is null ? new byte[0] : rArg;

        socket.Send(Encoding.UTF8.GetBytes(message.ToString()));

        socket.Send(lArg);
        socket.Send(rArg);

        Debug.Log(recipient);

        socket.Send(Encoding.UTF8.GetBytes(recipient));

        Debug.Log("END");
    }

    public static void ReceiveMessage(Message message, byte[] lArg, byte[] rArg, String sender)
    {
        switch (message)
        {
            case Message.MOVED:
                GameObject jumper = GameObject.Find(sender);
                jumper.transform.position = new Vector3(BitConverter.ToSingle(lArg, 0), BitConverter.ToSingle(rArg, 0), jumper.transform.position.z);
                break;
            case Message.JOINED:
                break;
            case Message.OUTED:
                playersData.Remove(sender);
                break;
            case Message.DATA:
                playersData.Add(sender, BitConverter.ToInt32(lArg, 0));
                break;
            case Message.START:
                StartStopGame.LoadLevel(BitConverter.ToInt32(lArg, 0));
                break;
        }
    }
}

По выводу клиента понятно, что он вполне нормально отсылает сообщения. Но по выводу сервера получается чушь. Сообщения смешиваются, данные куда-то пропадают, и появляются. Хотя клиентом было выслано только одно сообщение. Что происходит? В чём проблема? Заранее спасибо!


Ответы (0 шт):