unity - передача изображения с сервера на клиенты с помощью сокетов tcp. Нужна помощь в изменении кода - PullRequest
0 голосов
/ 03 мая 2018

Ниже приведен код, над которым я работаю. Я получил этот код по этой ссылке: ссылка на потоковое видео . Я изменил этот код для передачи файлов изображений, всякий раз, когда я нажимаю кнопку отправки в Unity. Изображения передавались с сервера клиенту, как и ожидалось. Проблема, с которой я сталкиваюсь, заключается в следующем:

  • всякий раз, когда я закрываю клиентское приложение и снова открываю, количество подключенных клиентов увеличивается.
  • не уверен, как отправить изображения большему количеству клиентов
  • когда серверное приложение закрыто и открыто, соединение не установлено / изображение не передается.
  • Также помогите, как я могу улучшить код лучше. Спасибо.

Код сервера:

using UnityEngine;
using System.Collections;
using System.IO;
using UnityEngine.UI;
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Collections.Generic;

public class ServerScript : MonoBehaviour
{
    public RawImage myImage;
    public bool enableLog = false;
    public Text logtext;

    Texture2D currentTexture;
    private TcpListener listner;
    private const int port = 7777;
    private bool stop = false;

    bool isConnected = false;
    TcpClient client = null;
    NetworkStream stream = null;

    private List<TcpClient> clients = new List<TcpClient>();

    //This must be the-same with SEND_COUNT on the client
    const int SEND_RECEIVE_COUNT = 15;

    private void Start()
    {
        Application.runInBackground = true;
        currentTexture = new Texture2D(300, 300);

        // Connect to the server
        listner = new TcpListener(IPAddress.Any, port);

        listner.Start();

        // Wait for client to connect in another Thread 
        Loom.RunAsync(() =>
            {
                while (!stop)
                {
                    // Wait for client connection
                    client = listner.AcceptTcpClient();
                    // We are connected
                    clients.Add(client);

                    isConnected = true;
                    stream = client.GetStream();
                }
            });

    }

    //send an image when the button is clicked
    public void sendButton(){
        //Start sending coroutine
        logtext.text = "Notsentimage";
        stop = false;
        StartCoroutine(senderCOR());
    }

    void OnGUI(){
        string ipaddress = Network.player.ipAddress;
        GUI.Box (new Rect (10, Screen.height - 50, 100, 50), ipaddress);
        GUI.Label (new Rect (20, Screen.height - 35, 100, 20), "Status" );
        GUI.Label (new Rect (20, Screen.height - 20, 100, 20), "Connected" + clients.Count);
    }

    //Converts the data size to byte array and put result to the fullBytes array
    void byteLengthToFrameByteArray(int byteLength, byte[] fullBytes)
    {
        //Clear old data
        Array.Clear(fullBytes, 0, fullBytes.Length);
        //Convert int to bytes
        byte[] bytesToSendCount = BitConverter.GetBytes(byteLength);
        //Copy result to fullBytes
        bytesToSendCount.CopyTo(fullBytes, 0);
    }

    //Converts the byte array to the data size and returns the result
    int frameByteArrayToByteLength(byte[] frameBytesLength)
    {
        int byteLength = BitConverter.ToInt32(frameBytesLength, 0);
        return byteLength;
    }

    IEnumerator senderCOR()
    {

        //Wait until client has connected
        while (!isConnected)
        {
            yield return null;
        }

        LOG("Connected!");

        bool readyToGetFrame = true;

        byte[] frameBytesLength = new byte[SEND_RECEIVE_COUNT];

        while (!stop)
        {
            currentTexture = myImage.texture as Texture2D;
            byte[] pngBytes = currentTexture.EncodeToPNG();
            //Fill total byte length to send. Result is stored in frameBytesLength
            byteLengthToFrameByteArray(pngBytes.Length, frameBytesLength);

            //Set readyToGetFrame false
            readyToGetFrame = false;

            Loom.RunAsync(() =>
                {
                    //Send total byte count first
                    stream.Write(frameBytesLength, 0, frameBytesLength.Length);
                    LOG("Sent Image byte Length: " + frameBytesLength.Length);

                    //Send the image bytes
                    stream.Write(pngBytes, 0, pngBytes.Length);
                    LOG("Sending Image byte array data : " + pngBytes.Length);
                    //logtext.text = "sentimage";

                    //Sent. Set readyToGetFrame true
                    readyToGetFrame = true;
                });

            //Wait until we are ready to get new frame(Until we are done sending data)
            while (!readyToGetFrame)
            {logtext.text = "sentimage";
                LOG("Waiting To get new frame");
                yield return null;
            }
            stop = true;
        }

    }


    void LOG(string messsage)
    {
        if (enableLog)
            Debug.Log(messsage);

    }

    private void Update()
    {

    }

    // stop everything
    public void OnApplicationQuit()
    {
        if (listner != null)
        {
            listner.Stop();
        }

        foreach (TcpClient c in clients)
            c.Close();
    }
}

Код клиента:

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

public class ClientScript : MonoBehaviour
{
    public RawImage image;
    //public InputField Ipinput;
    public Text Ipinput;
    public Text logtext;
    public Text infotext;
    public bool enableLog = true;
    bool disconnected = false;

    const int port = 7777;
    //public string IP = "192.168.0.101";
    TcpClient client;

    Texture2D tex;

    private bool stop = false;

    //This must be the-same with SEND_COUNT on the server
    const int SEND_RECEIVE_COUNT = 15;

    // Use this for initialization
    void Start()
    {
        Application.runInBackground = true;

        tex = new Texture2D(0, 0);
        client = new TcpClient();

        //Connect to server from another Thread
        Loom.RunAsync(() =>
            {
                LOGWARNING("Connecting to server...");
                // if on desktop
                client.Connect("192.168.0.102", port);

                // if using the IPAD
                //client.Connect(IPAddress.Parse(IP), port);
                LOGWARNING("Connected!");

                imageReceiver();
            });
    }

    void OnGUI(){

        string ipaddress = Network.player.ipAddress;
        GUI.Box (new Rect (10, Screen.height - 50, 100, 50), ipaddress);
        GUI.Label (new Rect (20, Screen.height - 30, 100, 20), "Status "+ client.Connected);
    }

    void imageReceiver()
    {
        //While loop in another Thread is fine so we don't block main Unity Thread
        Loom.RunAsync(() =>
            {
                while (!stop)
                {
                    //Read Image Count
                    int imageSize = readImageByteSize(SEND_RECEIVE_COUNT);
                    LOGWARNING("Received Image byte Length: " + imageSize);

                    //Read Image Bytes and Display it
                    readFrameByteArray(imageSize);
                }
            });
    }


    //Converts the data size to byte array and put result to the fullBytes array
    void byteLengthToFrameByteArray(int byteLength, byte[] fullBytes)
    {
        //Clear old data
        Array.Clear(fullBytes, 0, fullBytes.Length);
        //Convert int to bytes
        byte[] bytesToSendCount = BitConverter.GetBytes(byteLength);
        //Copy result to fullBytes
        bytesToSendCount.CopyTo(fullBytes, 0);
    }

    //Converts the byte array to the data size and returns the result
    int frameByteArrayToByteLength(byte[] frameBytesLength)
    {
        int byteLength = BitConverter.ToInt32(frameBytesLength, 0);
        return byteLength;
    }


    /////////////////////////////////////////////////////Read Image SIZE from Server///////////////////////////////////////////////////
    private int readImageByteSize(int size)
    {
        disconnected = false;

        NetworkStream serverStream = client.GetStream();
        byte[] imageBytesCount = new byte[size];
        var total = 0;
        do
        {
            var read = serverStream.Read(imageBytesCount, total, size - total);
            //Debug.LogFormat("Client recieved {0} bytes", total);
            if (read == 0)
            {
                disconnected = true;
                infotext.text = "disconnected";
                break;
            }
            total += read;
        } while (total != size);

        int byteLength;

        if (disconnected)
        {
            byteLength = -1;
        }
        else
        {   infotext.text = "connected";
            byteLength = frameByteArrayToByteLength(imageBytesCount);
        }
        return byteLength;
    }

    /////////////////////////////////////////////////////Read Image Data Byte Array from Server///////////////////////////////////////////////////
    private void readFrameByteArray(int size)
    {
        bool disconnected = false;

        NetworkStream serverStream = client.GetStream();
        byte[] imageBytes = new byte[size];
        var total = 0;
        do
        {
            var read = serverStream.Read(imageBytes, total, size - total);
            //Debug.LogFormat("Client recieved {0} bytes", total);
            if (read == 0)
            {
                disconnected = true;
                infotext.text = "disconnected";
                break;
            }
            total += read;
        } while (total != size);

        bool readyToReadAgain = false;

        //Display Image
        if (!disconnected)
        {
            infotext.text = "connected";
            //Display Image on the main Thread
            Loom.QueueOnMainThread(() =>
                {
                    displayReceivedImage(imageBytes);
                    readyToReadAgain = true;
                });
        }

        //Wait until old Image is displayed
        while (!readyToReadAgain)
        {
            System.Threading.Thread.Sleep(1);
        }

        //stop = true;
    }


    void displayReceivedImage(byte[] receivedImageBytes)
    {
        tex.LoadImage(receivedImageBytes);
        image.texture = tex;
    }


    // Update is called once per frame
    void Update()
    {
        if (disconnected){
        Loom.RunAsync(() =>
            {
                client.Connect("192.168.0.102", port);
                    disconnected = false;               
                });
        }
    }


    void LOG(string messsage)
    {
        if (enableLog)
            Debug.Log(messsage);
    }

    void LOGWARNING(string messsage)
    {
        if (enableLog)
            logtext.text = messsage;
    }

    public void OnApplicationQuit()
    {
        LOGWARNING("OnApplicationQuit");
        stop = true;

        if (client != null)
        {
            client.Close();
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...