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クラスを作成する必要があります.
データ処理ヘルプクラス:
クライアント:
サービス:
サーバ側でサーバに接続するクライアントを管理するClientクラス:
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();
}
}
プロジェクトアーキテクチャでは、通常、ヘッダデータと文字列データだけを送信しません.プロジェクトの必要に応じて、リクエストモジュールと応答モジュールも追加します.このブログがあなたを助けることができることを望みます!