0

Currently I'm trying to develop a multiplayer game with Unity. I checked the Unity's built-in Network and NetworkManager but I need the server dedicated. Hence I developed a java server and implements the protolbuf which is provided by Google. It works with my cocos project but not with this Unity one.

Two problems, first, no matter what did I send to server, the server side has a InvalidProtolBufferException :

While parsing a protocol message, the input ended unexpectedly in the middle > of a field. This could mean either than the input has been truncated or that > embedded message misreported its own length.

second, the stream.read method always makes my unity not responding. Here is my client-side code:

public class SocketClient : MonoBehaviour {

public Text send;
public Text read;

const string ipAddress = "192.168.0.233";
const int port = 8080;

TcpClient socket;
NetworkStream stream;
BinaryWriter bw;
BinaryReader br;

// Use this for initialization
void Start () {
    SetupSocket();    
}

void SetupSocket() {
    socket = new TcpClient(ipAddress, port);
    stream = socket.GetStream();
    bw = new BinaryWriter(socket.GetStream());
    br = new BinaryReader(socket.GetStream());
}

// Update is called once per frame
void Update () {
    ReadMessage();
}

public void SendMessage() {
    //NetworkStream stream = new NetworkStream(socket.Client);

    MessagesProto msg = new MessagesProto();
    msg.id = int.Parse(send.text);
    using (MemoryStream ms = new MemoryStream())
    {

        Serializer.Serialize<MessagesProto>(ms, msg);
        ms.Position = 0;
        byte[] data = ms.ToArray();
        ms.Position = 0;
        //foreach (byte d in data) {
        //    Debug.Log(d);
        //}

        stream.Write(data, 0 , data.Length);
    } 
}

public void ReadMessage() {
    if (stream.CanRead) {
        //byte[] receiveData = new byte[socket.ReceiveBufferSize];
        byte[] receiveData = new byte[4];
        socket.GetStream().Read(receiveData, 0, 4);
        Debug.Log("Loading...");
        using (MemoryStream ms = new MemoryStream()) {
            ms.Write(receiveData, 0, receiveData.Length);
            ms.Position = 0;
            var msg = Serializer.Deserialize<MessagesProto>(ms);
            read.text = msg.data + "";
        }
    }
}

}

I tried to set the stream.CanRead to stream.DataAvailable, no more crash but not reading anything either, these .Net sockets problems drive me crazy, anyone can help me with this please?

Cloud
  • 23
  • 2
  • Oh, btw, my Unity version is 5.3.3, and the code"byte[] receiveData = new byte[4]" is "byte[] receiveData = new byte[stream.ReceiveBufferSize]", also the next line is "socket.GetStream().Read(receiveDta, 0 , stream.ReceiveBufferSize); – Cloud May 11 '16 at 10:10
  • You may not get the entire message in one chunk. The ReadMessage() method must contain a while loop which reads the stream until all the data is received. – jdweng May 11 '16 at 10:30
  • So you mean every Update I receive a byte[] and .concat() them until the read buffer is blank? – Cloud May 11 '16 at 10:46

1 Answers1

1

It is not responding because your socket code is synchronous(blocking). You can solve this by either using asynchronous version of the socket functions or use Thread to do all your receiving stuff. This has been answered many times and I will just link to the answers.

TCP Server in Unity Just port the code to Client.

UDP.

Community
  • 1
  • 1
Programmer
  • 121,791
  • 22
  • 236
  • 328
  • I actually solved my problem by add a information length byte to my data byte array. However I'm still wondering if the client side could use multi threads since it is running on a mobile device – Cloud May 25 '16 at 04:13
  • @Cloud I answered this in my question. You can either use Thread or ignore it. Your app will either be freezing the UI and slow without Thread or it will be fast with another Thread. You decide. – Programmer May 25 '16 at 04:27