Unity 3 D開発のSocket通信

6056 ワード

最近ネットの同期を研究していて、とても面白いと感じます.サービス側もクライアントもc#で書かれています.残念ながら、現在のプロジェクトサービス側はc++またはjavaで書かれています.c#の書く効率はだめかもしれませんか?
socket通信プロトコルは私たちが知っている2つを通じて.1つはTCPプロトコルであり、1つはUDPプロトコルである.TCPはデータの伝送が安定してゲーム開発者の愛を勝ち取った.UDPはデータが落ちやすいため、正確なデータの伝送にはベンチを置かれているが、UDPの利点は伝送速度が速く、工業展示類のデータ伝送に適していることである.いくつかのデータをなくしても構わない.どうせ全体のデータの動きを分析しなければならない.
通常、TCPプロトコルを使用します.TCP伝送中に粘着パケットの問題が発生する.
接着:
我々が高周波数でいくつかの小さなデータを伝送すると,TCPプロトコルはこれらの小さなデータを自動的にパッケージ化して送信し,いわゆる粘着パケット問題を生じる.これはTCPの内部最適化である.
下請け:
一度に大量のデータを送信すると、TCPは自動的にデータを複数に分割してバッチで送信します.
解決策:私たちはデータを送信するたびに、データヘッダを追加します.通常、データヘッダはint 32タイプで、4バイトを占めます.データヘッダの内容は、私たちが送信したデータが何バイトを占めているかを示します.これにより,粘着パケットのデータに対して,データヘッダに基づいてデータを一歩一歩解析的に読み取ることができる.
次はSocket通信のコードセクションです.
まず、受信したデータを処理するためにmessageクラスを作成する必要があります.
データ処理ヘルプクラス:
public class Messgae
{
    //            
    private byte[] data=new byte[1024];
    //                              startIndex     0
    private int startIndex = 0;

    public byte[] Data { get { return data; } }

    public int StartIndex { get { return startIndex; } }

    public int RemainSize { get { return data.Length - startIndex; } }

  public void ReadMessage(int newDataAmount,Action ProcessCallback )
    {
        startIndex += newDataAmount;
        while (true)
        {
            if(startIndex<=4) return;
            int count = BitConverter.ToInt32(data, 0);
            //                      
            if (startIndex - 4 >= count)
            {
                //TODO     
                ActionCode actionCode = (ActionCode)BitConverter.ToInt32(data, 4);
                Debug.Log(actionCode);
                string s = Encoding.UTF8.GetString(data, 8, count - 4);
                Debug.Log(s);
                ProcessCallback(actionCode,s);//                            
                Array.Copy(data,count+4,data,0,startIndex-4-count);//                              
                startIndex -= (count + 4);
            }
        }
    }

クライアント:
public class ClientManager : BaseManager
{
    private static string IP = "";
    private static int PORT = 8888;

    private Socket clientSocket;
    Messgae message=new Messgae();

    void StartClientSocket()
    {
        clientSocket=new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp);
        IPEndPoint ipEndPoint=new IPEndPoint(int.Parse(IP),PORT);
        try
        {
            clientSocket.Connect(ipEndPoint);
            StartReceieve();
        }
        catch (Exception e) 
        {
            Debug.Log("        !"+e);
        }
    }

    void StartReceieve()
    {
        //                          message            
        clientSocket.BeginReceive(message.Data, message.StartIndex, message.RemainSize, SocketFlags.None,
            ReceieveCallBack, null);
    }

    private void ReceieveCallBack(IAsyncResult ar )
    {
        try
        {
            int count = clientSocket.EndReceive(ar);
            message.ReadMessage(count);//        message            
            StartReceieve();
        }
        catch (Exception e)
        {
            Debug.Log("         "+e);
        }
    }

    //        
    private void Send(byte[] data)
    {
        clientSocket.Send(data);
    }

サービス:
class Server
    {
        private Socket serverSocket;
        private IPEndPoint ipEndPoint;

        private List clientList=new List();
        private ControllerManager controllerMgr;

        public Server() { }

        public Server(string ip, int port)
        {
            controllerMgr=new ControllerManager(this);
            ipEndPoint = new IPEndPoint(IPAddress.Parse(ip), port);
        }

        public void Start()
        {
            serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            serverSocket.Bind(ipEndPoint);
            serverSocket.Listen(0);//0                 
            serverSocket.BeginAccept(AcceptCallBack, null);//AcceptCallback                  
        }

        private void AcceptCallBack(IAsyncResult ar)
        {
            Socket clientSocket = serverSocket.EndAccept(ar);
            Client client = new Client(clientSocket, this);//        Client                
            clientList.Add(client);
            client.Start();
            serverSocket.BeginAccept(AcceptCallBack, null);
        }
    }

サーバ側でサーバに接続するクライアントを管理するClientクラス:
class Client
    {
        private Socket clientSocket;
        private Server server;
        private Message message = new Message();

        public Client(Socket clientSocket, Server server)
        {
            this.clientSocket = clientSocket;
            this.server = server;
        }

        public void Start()
        {
	    //                        
            if(clientSocket==null||clientSocket.Connected==false) return;
            clientSocket.BeginReceive(message.Data, message.StartIndex, message.RemainSize, SocketFlags.None,
                ReceieveCallback, null);
        }

        private void ReceieveCallback(IAsyncResult ar)
        {
            try
            {
		//                        
                if (clientSocket == null || clientSocket.Connected == false) return;
                int count = clientSocket.EndReceive(ar);
                if (count == 0)
                {
                    Close();
                }
                Start();
            }
            catch (Exception e)
            {
                Console.WriteLine("       !" + e);
            }
        }

       

        public void Send(byte[] bytes)
        {
            clientSocket.Send(bytes);
        }

        private void Close()
        {
            if (clientSocket != null)
                clientSocket.Close();
        }
    }
プロジェクトアーキテクチャでは、通常、ヘッダデータと文字列データだけを送信しません.プロジェクトの必要に応じて、リクエストモジュールと応答モジュールも追加します.このブログがあなたを助けることができることを望みます!