2

Unityアプリがtcpデータを取り込めるように設定できました。ただし、プロジェクトを実行すると、アプリケーション全体がフリーズし、メッセージを受信するまで何もしません。次に、メッセージが受信されると、そのメッセージを出力し、クライアントが再度接続することを許可しません。

このコードは、私の TCP 読み取りクラス全体です。これを引き起こしている愚かなことがここで行われていますか?

TCP データを読み取るためのより良い方法はありますか?

using UnityEngine;
using System.Collections;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System;
using System.IO;

public class TCPConnection: MonoBehaviour 
{
    public string ip_address = "";
    public int port_number = 0;

     void Start()
    {

        try
        {
            IPAddress ipAddress = IPAddress.Parse(ip_address);
            TcpListener listener = new TcpListener(ipAddress, port_number);
            listener.Start();
            print("The server is running at port " + port_number);
            print("The local end point is :" + listener.LocalEndpoint);
            print("Waiting for connection.....");

            Socket socket = listener.AcceptSocket();
            print("Connection accepted from " + socket.RemoteEndPoint);

            byte[] b = new byte[100];
            int k = socket.Receive(b);
            print("recieved...");
            for (int i = 0; i < k; i++)
                print (Convert.ToChar(b[i]));

            ASCIIEncoding ascii = new ASCIIEncoding();
            socket.Send(ascii.GetBytes("The string was recieved by the server"));
            print("\nSent ack");

        }

        catch (Exception e)
        {
            print("error...." + e.Message);
        }

    }
}
4

2 に答える 2

2

listener.AcceptSocketおよびsocket.Receiveはブロッキング コールです。したがって、UI がフリーズするのは正常です。最初の接続を受け入れた後はlistener.AcceptSocke、新しいコレクションを取得するために再度呼び出すことはありません。

これらのメソッドを使用する一般的な方法は、非同期呼び出し、スレッド、またはタスクを使用することです。

編集

例:

void Start()
{
    Task.Factory.StartNew(() =>
        {
            TcpListener listener = new TcpListener(IPAddress.Any, 12345);
            listener.Start();

            while (true)
            {
                Socket socket = listener.AcceptSocket();
                Task.Factory.StartNew(() =>
                {
                    byte[] b = new byte[100];
                    int k = socket.Receive(b);
                });
            }
        });
}
于 2013-09-26T18:27:20.397 に答える
0

socket.Receive(b);とはAccept()、データを受信するまで現在のスレッドをブロックします。ここでいくつかのことを実行できます。

1) データを受信した別のスレッドを作成し、メインスレッドによってチェックされるキューに入れます。ただし、これは多くのクライアントが接続している場合には推奨されません。

2) ソケットの非同期メソッドを使用できます: ここに例を示します: http://csharp.vanlangen.biz/network-programming/async-sockets/asyncsocketreader/ 非ブロッキング リスナーの例もあります。

非同期リスナーは次のようになります。

public class SocketEventArgs : EventArgs
{
    public Socket Socket { get; private set; }

    public SocketEventArgs(Socket socket)
    {
        Socket = socket;
    }
}

/// <author>Jeroen van Langen</author>
/// <source>http://http://csharp.vanlangen.biz/network-programming/async-sockets/easysocketlistener/</source>
public class EasySocketListener : IDisposable
{
    private Socket _socket;

    public void Start(int port)
    {
        _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        _socket.Bind(new IPEndPoint(IPAddress.Any, port));
        _socket.Listen(8);

        StartAccepting();
    }

    private void StartAccepting()
    {
        try
        {
            _socket.BeginAccept((asyncResult) =>
            {
                try
                {
                    Socket clientSocket = _socket.EndAccept(asyncResult);
                    if (OnSocketAccept != null)
                        OnSocketAccept(this, new SocketEventArgs(clientSocket));

                    StartAccepting();
                }
                catch { }
            }, null);
        }
        catch { }
    }

    public void Dispose()
    {
        if (_socket != null)
        {
            _socket.Dispose();
            _socket = null;
        }
    }

    public event EventHandler<SocketEventArgs> OnSocketAccept;
}

OnSocketAccept は、新しいクライアントが接続されると呼び出されます。

于 2013-09-26T18:29:12.560 に答える