Сокеты. Непонятные сообщения и странные выводы
У меня есть некий удалённый сервер с таким кодом:
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;
}
}
}
По выводу клиента понятно, что он вполне нормально отсылает сообщения. Но по выводу сервера получается чушь. Сообщения смешиваются, данные куда-то пропадают, и появляются. Хотя клиентом было выслано только одно сообщение. Что происходит? В чём проблема? Заранее спасибо!