Search Unity

Send PNG from Server to Client and via versa ?

Discussion in 'Multiplayer' started by Muckel, Aug 17, 2015.

  1. Muckel

    Muckel

    Joined:
    Mar 26, 2009
    Posts:
    471
    Hello,
    i'm try to figure out how to send a small png file 100-200k from Server/Client to Client and via versa.
    I have this script here but it doesn't work...
    Also i never had used the Network writer before and so no idea if i'm on the right trail...
    Is there a example how to send a user image over network?
    If someone has a idea or know how please feel free to comment here...
    many many thxx
    M.

    Code (CSharp):
    1.  
    2.  
    3. using UnityEngine;
    4. using System.Collections;
    5. using UnityEngine.Networking;
    6. using UnityEngine.Networking.NetworkSystem;
    7.  
    8. public class SendTexture : NetworkBehaviour {
    9.  
    10. public Texture2D playerTexture;
    11. public Texture2D tempTexture;
    12. private byte[] textureData;
    13.  
    14. void Start(){
    15. if (!isServer){
    16.     playerTexture = tempTexture;
    17. Debug.Log(isLocalPlayer);
    18. }
    19. }
    20. public void SendImage(){
    21.              byte[] textureData = playerTexture.EncodeToPNG();
    22.              NetworkWriter writer = new NetworkWriter();
    23.              writer.WriteBytesFull(textureData);
    24.              byte[] data = writer.AsArray();
    25.  
    26.              CmdServerTextureUpdate(data);
    27.          }
    28.  
    29. [Command(channel=3)]
    30. void CmdServerTextureUpdate(byte[] data) {
    31.       RpcClientTextureUpdate(data);
    32. }
    33.  
    34. [ClientRpc]
    35. void RpcClientTextureUpdate(byte[] data) {
    36.      playerTexture.LoadImage(data);
    37.      playerTexture.Apply();
    38. }
    39.  
     
    Last edited: Aug 17, 2015
  2. ObliviousHarmony

    ObliviousHarmony

    Joined:
    Jul 3, 2014
    Posts:
    79
    Hello,

    Commands must have a "Cmd" in front of the method name, so "CmdTextureUpdate()" or something like that, instead. RPC calls must have an "Rpc" in front, so "RpcTextureUpdate()"
     
  3. Muckel

    Muckel

    Joined:
    Mar 26, 2009
    Posts:
    471
    thx,
    yes i have these commands in front... just forgot it when i only use the part of Script... i fixed it above...
    thx
     
  4. Muckel

    Muckel

    Joined:
    Mar 26, 2009
    Posts:
    471
    Hello,
    sry i was not very precise... i get this error message:
     
  5. Muckel

    Muckel

    Joined:
    Mar 26, 2009
    Posts:
    471
    Hello,
    well i narrowed the problem down...
    I have now a tiny texture 2.0KB RGB < MTU1500 bytes
    If i use the NetworkWriter to send the bytes something comes over but not the texture...
    so if i try like this i got a ? as texture:
    Code (CSharp):
    1. NetworkWriter writer = new NetworkWriter();
    2.              writer.WriteBytesFull(textureData);
    3.              byte[] data = writer.ToArray();
    4.      
    5.             Texture2D receivedTexture = new Texture2D(16, 12, TextureFormat.RGB24, false);
    6.             receivedTexture.LoadImage(data);
    7.             textureObjectOriginal.GetComponent<Renderer>().material.SetTexture("_MainTex", receivedTexture);
    does anyone know how to write the bytes in the correct way?
    many thx
    M.
     
  6. Kajiryu

    Kajiryu

    Joined:
    Dec 25, 2012
    Posts:
    1
    I also had a lot of problems sending byte arrays over the network.
    • Check if your channel type is "Reliable Fragmented"
    • Don't use Commands or RPCCalls for big byte arrays. I think they have a fragment size limitation which is not configurable yet. I am not sure if they fixed that, but you can try to change the values of "networkManager.connectionConfig.FragmentSize" and "networkManager.connectionConfig.MaxSentMessageQueueSize" and see if it works
    • As a last resort try using NetworkMessages and sending them with client.SendByChannel(messageID, message, channel).
    I ended up with NetworkMessages in combination with "MaxSentMessageQueueSize = 512". Worked fine when I sent PNGs with the size around 40kB
     
    Muckel likes this.
  7. Muckel

    Muckel

    Joined:
    Mar 26, 2009
    Posts:
    471
    thank you & welcome !
    this brings me a step further :)
     
  8. Dreamteck

    Dreamteck

    Joined:
    Feb 12, 2015
    Posts:
    336
    I just posted a thread about something else but in it there is an explanation for our file sending approach (which works with big files too). http://forum.unity3d.com/threads/increase-bandwidth-restriction.348606/ see if that helps.
    Basically I'm sending messages, not using RPCs (but that doesn't matter).
    The max packet size for ReliableSequenced is 1500 bytes. Subtracting all the information like ip, timestamps and what not that's been sent with a NetworkMessage that makes the bytes under 1400. I'm not sure if that's the case with RPCs but it is with NetworkServer.Send and NetworkClient.Send.
    ReliableSequenced however can be up to 64000 bytes big (again, less than that because of all the other information).
    So if you want to send a file bigger than 64kb you will have to manually segment the file and send it.
    What I have is two classes:
    - One for loading all sorts of files into a byte array and keeping information about the files (names, sizes, types..) - GameFile
    - And one for sending the files which contains methods for receiving files and getting file chunks from the file - FileTransferHandler

    When sending the file I use the FileTransferHandler to get small chunks from the GameFile and send them using a ReliableSequenced channel. Basically the handler contains a byte index which holds the information about how much of the file is sent (for example if the index is 1299, then I have only sent 1300 bytes so the next chunk will start from the 1300 index and so on and so on).

    Prior to sending the chunks, I send a message to the receiver telling them what type of file they are going to be receiving, the name, the size (the receiver has to know how big is this file so it knows when the files has been received) and other information. The receiver then adds an empty file to a file buffer and every time the receiver receives a chunk it feeds it to that file in the buffer until the file is complete.

    Of course you need to have unique file identifiers (could be an int, could be a string) to be able to tell which byte chunk is for which received file.

    Also, don't send all of the byte chunks in one go. Send for example 10 or 20 chunks and wait for a reply from the receiver (my receiver replies on the final chunk e.g. if I send 10 chunks at a time, the receiver will reply after the tenth chunk has been received). If you send all of the chunks in one go you will clog the network.

    I hope that helps :)
     
  9. Muckel

    Muckel

    Joined:
    Mar 26, 2009
    Posts:
    471
    @ Dreamteck
    many many thx!
    These infos help me allot!
    chunks is the way to go :) !
    Got a prototype work!
    Thank you
    M.
     
  10. ShantuApps

    ShantuApps

    Joined:
    Apr 25, 2016
    Posts:
    14
    Can you please provide chunk related code (client and server)
     
    wilkens likes this.
  11. ShantuApps

    ShantuApps

    Joined:
    Apr 25, 2016
    Posts:
    14
    Hi, can you please share your prototype code
     
  12. yerriswamy

    yerriswamy

    Joined:
    Apr 10, 2015
    Posts:
    2
    Hi can you please share me the prototype code to send a image i am getting same error..
     
  13. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    How much "prototype" code you wrote 4 years ago do you have sitting around ready to share?
     
  14. MarkoHazel

    MarkoHazel

    Joined:
    Apr 5, 2020
    Posts:
    15
    Hi, do you have a sample of your code for smaller PNG files? It may help me immensely!