0

I wanna make socket networking program with Unity so I made test project and added NetworkManager class and PacketManager class in that project for test.

When the program starts, I call connect() method in NetworkManager, then network connection is succeed. And I have to make packet to bytestream for sending to server. So I made PacketManager class(static) using marshaling and a call for getBytes() method. But It doesn't work (unity program is terminated).

Here are my scripts

Move.cs

using UnityEngine;
using System.Collections;
using System.Net.Sockets;
using System.Net;
using System;
using System.Runtime.InteropServices;

public class move : MonoBehaviour {

    private NetworkManager nManager;

    // Use this for initialization
    void Start () {
        Debug.Log ("start");

        nManager = new NetworkManager ();
        nManager.connect ();

        packet p = new packet();
        p.type = 100;
        p.msg = "abcdabcd";

        byte[] array = PacketManager.getBytes (p);

    }

    // Update is called once per frame
    void Update () {

    }
}

NetworkManager.cs

using UnityEngine;
using System.Collections;
using System.Net.Sockets;
using System.Net;
using System;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct packet
{
    public int type;
    public int number;
    public int room;
    public float x, y, z;
    public float rotate;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)]
    public string msg;
}

public class NetworkManager : MonoBehaviour
{
    private const string serverIP = "127.0.0.1";
    private const int portNum = 9090;
    private const int buffersize = 128;

    private static TcpClient client = null;
    private static NetworkStream netStream = null;

    public NetworkManager() {}

    public Boolean connect()
    {
        Boolean success = false;

        try
        {
            Debug.Log("try to connenct..");
            client = new TcpClient(serverIP, portNum);
            netStream = client.GetStream();
            Debug.Log("connected success!");

        }
        catch (Exception e)
        {
            success = false;
            Debug.Log(e.Message);
        }

        return success;
    }

    public void sendPacket(packet p)
    {
        byte[] array = PacketManager.getBytes(p);
        netStream.Write(array, 0, buffersize);
    }

    public packet recvPacket()
    {
        packet p = new packet();
        byte[] bytebuffer = new Byte[buffersize];
        int totalByteRcvd = 0;
        int bytesRcvd = 0;

        while (totalByteRcvd < buffersize)
        {
            if ((bytesRcvd = netStream.Read(bytebuffer, totalByteRcvd, buffersize - totalByteRcvd)) == 0)
            {

                p = PacketManager.BytesToSturct<packet>(bytebuffer);

                break;
            }
            totalByteRcvd += bytesRcvd;
            Debug.Log("byte : " + totalByteRcvd);
        }

        return p;
    }

}

PacketManager.cs

using UnityEngine;
using System.Collections;
using System.Net.Sockets;
using System.Net;
using System;
using System.Runtime.InteropServices;

public class PacketManager : MonoBehaviour
{

    public static byte[] getBytes(object str)
    {

        int size = Marshal.SizeOf(str);
        byte[] arr = new byte[size];
        IntPtr ptr = Marshal.AllocHGlobal(size);

        Marshal.StructureToPtr(str, ptr, true);
        Marshal.Copy(ptr, arr, 0, size);
        Marshal.FreeHGlobal(ptr);

        return arr;
    }

    public static T BytesToSturct<T>(byte[] buffer) where T : struct
    {
        int size = Marshal.SizeOf(typeof(T));

        IntPtr ptr = Marshal.AllocHGlobal(size);
        Marshal.Copy(buffer, 0, ptr, size);
        T obj = (T)Marshal.PtrToStructure(ptr, typeof(T));
        Marshal.FreeHGlobal(ptr);

        return obj;
    }

}

If I remove:

byte[] array = PacketManager.getBytes (p);

in move.cs, Logs are printed well, but if i call any method (not only that method), program terminated.

What is the problem?

armatita
  • 12,825
  • 8
  • 48
  • 49
최혜정
  • 3
  • 2
  • **unity program is terminated** what does that mean? Freezing? – Programmer Jun 11 '16 at 13:01
  • Can you debug to the line cause your programm to fail? What does terminated mean? Crash, ErrorMessage, Frezze? – Master117 Jun 11 '16 at 13:13
  • i mean, "Unity Editor has stopped working" message is pop and unity program suddenly exited and go to Desktop(i have to reopen unity program) so i cannot check log msg – 최혜정 Jun 11 '16 at 13:20

1 Answers1

2

"Unity Editor has stopped working" message is pop and unity program suddenly exited and go to Desktop(i have to reopen unity program) so i cannot check log msg

I can spot few problems in your code.

1.You are using a synchronous socket without Thread. When using a synchronous socket, you have must use it with a Thread or it will freeze Unity while waiting for client to connect, connecting to server or while waiting to receive from client.

Another solution is to use asynchronous socket. You don't need Thread to use it.

2.while (totalByteRcvd < buffersize). This will instantly freeze Unity until totalByteRcvd >= buffersize and before that happens, netStream.Read must return but that won't happen anytime soon because of the problem in #1.

So make your recvPacket() function a void function the call it like this:

receive();

void receive()
{
    System.Threading.Thread socketThread = new System.Threading.Thread(recvPacket);
    socketThread.Start();
}

This should fix your freezing problems. If that doesn't work, then there are also other problems in your code. Use a working server socket code from here. You can simply convert it into a client code.

Community
  • 1
  • 1
Programmer
  • 121,791
  • 22
  • 236
  • 328
  • Yup. Basically, anything related to Marshal Class in Unity –  Jun 15 '16 at 06:58
  • 1
    @Mark Used Marshal class to make a plugin long time ago and had no problem with it. The link you posted says that this problem is fixed in 5.4 and I use 5.4.0.13b. I've answered many network question here and by looking at her code, the freezing is because she is not using asynchronous socket. She is using synchronous which means that `Stream.Read` will block until something is received. If she puts her synchronous network receive code in another `Thread`, that should be solved as long as her network code has been tested in C# and works as expected. – Programmer Jun 15 '16 at 08:50
  • 1
    HAHH! I need to try and fiddle around with this in Unity again! Thanks for the details, appreciated! –  Jun 15 '16 at 09:26