UnityにおけるSocket通信プログラミングの同期実装
10777 ワード
サービス側
サービス側の主な役割は、各クライアントから送信されたデータを処理することであるため、クライアントのSocketプログラミングでは、クライアントの要求をループ処理するために2つのスレッドを使用する必要があり、1つのスレッドはクライアントの接続状況を傍受するために使用され、1つのスレッドはクライアントのメッセージ送信を傍受するために使用される.サービス側がクライアントのメッセージを受信した後、メッセージを処理して各クライアントに配布する必要がある.
基本プロセス
using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace TCPLib {
public class TCPServer {
private byte[] result = new byte[1024];
private int maxClientCount; //
public int MaxClientCount {
get {
return maxClientCount;
}
set {
maxClientCount = value;
}
}
//IP
private string ip;
public string IP {
get {
return ip;
}
set {
ip = value;
}
}
//
private int port;
public int Port {
get {
return port;
}
set {
port = value;
}
}
//
private List < Socket > mClientSockets;
public List < Socket > ClientSockets {
get {
return mClientSockets;
}
}
//IP
private IPEndPoint iPEndPoint;
// Socket
private Socket mServerSocket;
// Socket
private Socket mClientSocket;
public Socket ClientSocket {
get {
return mClientSocket;
}
set {
mClientSocket = value;
}
}
///
///
///
///
///
public TCPServer(int port, int count) {
this.ip = IPAddress.Any.ToString();
this.port = port;
this.maxClientCount = count;
this.mClientSockets = new List < Socket > ();
// IP
this.iPEndPoint = new IPEndPoint(IPAddress.Parse(ip), port);
// Socket
this.mServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//
this.mServerSocket.Bind(this.iPEndPoint);
//
this.mServerSocket.Listen(maxClientCount);
}
///
///
///
/// ip
///
///
public TCPServer(string ip, int port, int count) {
this.ip = ip;
this.port = port;
this.maxClientCount = count;
this.mClientSockets = new List < Socket > ();
// IP
this.ipEndPoint = new IPEndPoint(IPAddress.Parse(ip), port);
// Socket
this.mServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//
this.mServerSocket.Bind(this.ipEndPoint);
//
this.mServerSocket.Listen(maxClientCount);
}
public void Start() {
// ,
var mServerThread = new Thread(this.ListenClientConnect);
mServerThread.Start();
}
//
private void ListenClientConnect() {
//
bool flag = true;
while (flag) {
//
this.ClientSocket = this.mServerSocket.Accept();
//
this.mClientSockets.Add(this.ClientSocket);
this.SendMessage(string.Format(" {0} ", this.ClientSocket.RemoteEndPoint));
// ,
var mReceiveThread = new Thread(this.ReceiveClient);
mReceiveThread.Start(this.ClientSocket);
}
}
//
private void ReceiveClient(object obj) {
//
var mClientSocket = (Socket) obj;
bool flag = true;
while (flag) {
try {
//
int receiveLength = mClientSocket.Receive(result);
//
string clientMessage = Encoding.UTF8.GetString(result, 0, receiveLength);
//
this.SendMessage(string.Format(" {0} :{1}", mClientSocket.RemoteEndPoint, clientMessage));
} catch (Exception e) {
//
this.mClientSockets.Remove(mClientSocket);
this.SendMessage(string.Format(" : {0} , :{1}", mClientSocket.RemoteEndPoint, e.Message));
//
mClientSocket.Shutdown(SocketShutdown.Both);
mClientSocket.Close();
break;
}
}
}
//
public void SendMessage(string msg) {
if (msg == string.Empty || this.mClientSockets.Count <= 0) return;
foreach(Socket s in this.mClientSockets) {
(s as Socket).Send(Encoding.UTF8.GetBytes(msg));
}
}
///
///
///
/// ip
/// port
/// message
public void SendMessage(string ip, int port, string msg) {
//
IPEndPoint _IPEndPoint = new IPEndPoint(IPAddress.Parse(ip), port);
//
foreach(Socket s in mClientSockets) {
if (_IPEndPoint == (IPEndPoint) s.RemoteEndPoint) {
s.Send(Encoding.UTF8.GetBytes(msg));
}
}
}
}
}
サービス側の列:
using System;
using System.Collections.Generic;
using System.Text;
using TCPLib;
using System.Net;
using System.Net.Sockets;
namespace TCPLib.Test
{
class Program
{
static void Main(string[] args)
{
// IP
TCPLib.TCPServer s1 = new TCPServer(“127.0.0.1”, 6001, 10);
//
TCPLib.TCPServer s2 = new TCPServer(6001, 10);
// Start
s1.Start();
}
}
}
クライアント
クライアントはサービス側と通信するだけでよいため、サービス側と通信する必要があるが、サーバと通信する過程で常に接続をスムーズに保つ必要があるため、接続状況の傍受とメッセージ送信の傍受をそれぞれ処理するために2つのスレッドが必要である.
基本プロセス
using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace TCPLib
{
public class TCPClient
{
private byte[] result = new byte[1024];
///
/// IP
///
private string ip;
public string IP
{
get { return ip; }
set { ip = value; }
}
///
///
///
private int port;
public int Port
{
get { return port; }
set { port = value; }
}
///
/// IP
///
private IPEndPoint ipEndPoint;
///
/// Socket
///
private Socket mClientSocket;
//
private bool isConnected = false;
///
///
///
/// IP
///
public TCPClient(string ip,int port)
{
this.ip = ip;
this.port = port;
// IP
this.ipEndPoint= new IPEndPoint(IPAddress.Parse(this.ip), this.port);
//
mClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
}
public void Start()
{
//
var mConnectThread = new Thread(this.ConnectToServer);
//
mConnectThread.Start();
}
//
private void ConnectToServer()
{
while(!isConnected)
{
try
{
mClientSocket.Connect(this.ipEndPoint);
this.isConnected = true;
}
catch(Exception e)
{
Console.WriteLine(string.Format(" , , :{0}", e.Message));
this.isConnected = false;
}
// 5
Thread.Sleep(5000);
Console.WriteLine(" ...");
}
Console.WriteLine(" , ");
//
var mReceiveThread = new Thread(this.ReceiveMessage);
mReceiveThread.Start();
}
private void ReceiveMessage()
{
bool flag = true;
while(flag)
{
try
{
//
int receiveLength = this.mClientSocket.Receive(result);
//
string serverMessage = Encoding.UTF8.GetString(result, 0, receiveLength);
//
Console.WriteLine(serverMessage);
}
catch(Exception e)
{
flag = false;
//
this.mClientSocket.Shutdown(SocketShutdown.Both);
this.mClientSocket.Close();
//
this.isConnected = false;
ConnectToServer();
}
}
}
private void SendMessage(string msg)
{
if (msg == string.Empty || this.mClientSocket == null) return;
mClientSocket.Send(Encoding.UTF8.GetBytes(msg));
}
}
}
クライアントの列:
using System;
using System.Collections.Generic;
using System.Text;
using TCPLib;
using System.Net;
using System.Net.Sockets;
namespace TCPLib.Test
{
class Program
{
static void Main(string[] args)
{
//
TCPLib.TCPClient c = new TCPClient("127.0.0.1", 6001);
// Start
c.Start();
while (true)
{
//
string msg = Console.ReadLine();
//
c.SendMessage(msg);
}
}
}
}
まとめ:
これは基本的な例ですが、この例では現在、以下の問題があります.*ここでは文字列を送信する機能しか実現されていません.このプログラムは、基礎的なint、float、double、string、singleなどのタイプからstructure、class、さらにバイナリファイルのタイプまで、より多くのタイプをサポートする方法がありますか.*この例を拡張するには、すべてのSocketプログラミングプロセスが同じであることがわかります.唯一の違いは、コア機能とカスタム機能を分離できないため、データを受信した後にどのように処理するかです.*今日のこの例では、データ転送のバッファサイズを人為的に1024に設定しています.この設定よりも大きなデータ型に遭遇した場合、この例は変更する必要があります.
このunityチュートリアルでは、socket同期通信についてこれで終わります.