We try to send an image from server to client over a reliable fragmented channel in UNET. We get an error if we exceed the buffer size (max. ~64000 byte). Have we forgotten to define any attributes for fragmented channel or should it fragment by itself?
We are using Unity 2018.4
We’ve tried to make the buffer size “dynamic”, by defining it as the length of the serialized message. And on the Client side we have a buffer size of 64000. We have the impression, that the fragmentation doesn’t happen automatically.
Here are some relevant snippets from our code
Server side (sender)
NetworkTransport.Init();
ConnectionConfig cc = new ConnectionConfig();
reliableChannel = cc.AddChannel(QosType.Reliable);
reliableFragmentedChannel = cc.AddChannel(QosType.ReliableFragmented); //here we add the reliable fragmented channel
HostTopology topo = new HostTopology(cc, MAX_USER);
//This function should send fragmented messages.
public void SendClientFragmented(int recHost, int connectionId, NetMsg msg)
{
// This is where we hold our data
//byte[] buffer = new byte[BYTE_SIZE];
// This is where you would crush your data into a byte[]
BinaryFormatter formatter = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
formatter.Serialize(ms, msg);
byte [] serializedStructure = ms.ToArray();
Debug.Log("Structure Length:" + serializedStructure.Length);
//if (recHost == 0)
NetworkTransport.Send(hostId, connectionId, reliableFragmentedChannel, serializedStructure, serializedStructure.Length, out error);
//Our function to send the image (the Arrays are in case of multiple clients logged in). This function is called in the next section
public void SendImageToClient(byte[] byteTexture)
{
int[] recHostIdArray = recHostIdList.ToArray();
int[] connectionIdArray = connectionIdList.ToArray();
int[] channelIdArray = channelIdList.ToArray();
Net_SendImage im = new Net_SendImage();
im.imageByte = byteTexture;
SendClientFragmented(recHostIdArray[0], connectionIdArray[0], im);
}
//Here we transform the image to a byte array
public void OnClickSendImage()
{
Texture2D image = (Texture2D)GameObject.Find("PhotoDisplay").GetComponent<Renderer>().material.mainTexture;
byte[] jpgBytes = image.EncodeToJPG(10); //Vielleicht Länge des byte arrays mitsenden.
Debug.Log("Byte Array created");
Server.Instance.SendImageToClient(jpgBytes);
}
Here’s the Client side code for receiving the byte array:
private const int BYTE_SIZE = 64000;
//Reliable Fragmented channel definition
NetworkTransport.Init();
ConnectionConfig cc = new ConnectionConfig();
reliableChannel = cc.AddChannel(QosType.Reliable);
reliableFragmentedChannel = cc.AddChannel(QosType.ReliableFragmented);
HostTopology topo = new HostTopology(cc, MAX_USER);
//Receiving messages
NetworkEventType type = NetworkTransport.Receive(out recHostId, out connectionId, out channelId, recBuffer, BYTE_SIZE, out dataSize, out error);
switch (type)
{
case NetworkEventType.Nothing:
break;
case NetworkEventType.ConnectEvent:
Debug.Log("We have connected to the Server");
break;
case NetworkEventType.DisconnectEvent:
Debug.Log("We have been disconnected!");
break;
case NetworkEventType.DataEvent:
BinaryFormatter formatter = new BinaryFormatter();
MemoryStream ms = new MemoryStream(recBuffer, 0, dataSize);
ms.Seek(0, SeekOrigin.Begin);
//ms.Write(recBuffer, 0, recBuffer.Length);
Debug.Log("Datasize: " + dataSize);
NetMsg msg = (NetMsg)formatter.Deserialize(ms);
OnData(connectionId, channelId, recHostId, msg);
break;
default:
case NetworkEventType.BroadcastEvent:
Debug.Log("Unexpected network event type");
break;
}
We expect our image bytearray being fragmented automatically and send over to the client. What should we add or are we having a bad approach?
Thanks for any help!