2016-05-08 29 views
3

背景

我有它發送二進制從數據採集設備簡單的工作服務器,套接字連接作品和我的兩個統一的客戶和其他客戶端(如MATLAB客戶端)可以接收數據正確。統一處理數據流從插座

然後,Unity中的一個客戶端試圖從該服務器接收數據,並將每個數據包的字節分段爲三維座標數組。

每一幀應該是512x424像素超大,所以這就是爲什麼我要等到數據填充512x424字節做分割

的問題

統一罰款運行在套接字連接,並接收階段,這將在處理階段卡住(攤主):ProcessFrame((byte[])state.buffer.Clone())

我已閱讀本SO帖子: Getting UdpClient Receive data back in the Main thread 和改變了我相應的代碼,但問題仍然存在。

我做錯了什麼?感謝您的幫助:)

代碼---客戶

public class SomeClass: MonoBehaviour { 
public GameObject sphere; 
const int IMGW = 512; 
const int IMGH = 424; 
const int MAXBODY = 6; 
const int NUMJOINT = 25; 
const int READ_BUFFER_SIZE = (4 * 3 + 4 * 1 + 4 * 1) * (IMGW * IMGH + MAXBODY * NUMJOINT); 
const int PORT_NUM = 20156; 
public string response = String.Empty; 
private Queue queue; 
private System.Object queueLock; 
private int bytesRead; 
// ManualResetEvent instances signal completion. 
private static ManualResetEvent connectDone = 
    new ManualResetEvent(false); 
private static ManualResetEvent sendDone = 
    new ManualResetEvent(false); 
private static ManualResetEvent receiveDone = 
    new ManualResetEvent(false); 

// State object for receiving data from remote device. 
public class StateObject 
{ 
    // Client socket. 
    public Socket workSocket = null; 
    // Receive buffer. 
    public const int BufferSize = (4 * 3 + 4 * 1 + 4 * 1) * (IMGW * IMGH + MAXBODY * NUMJOINT); 
    public byte[] buffer = new byte[BufferSize]; 
} 

// We use this to keep tasks needed to run in the main thread 
private static readonly Queue<Action> tasks = new Queue<Action>(); 

// Use this for initialization 
void Start() { 
    queueLock = new object(); 
    queue = new Queue(); 
    this.StartClient(); 

    // Test object  
    sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere); 
    sphere.transform.position = new Vector3(0, -1, 10);  
}   
    // Update is called once per frame 
void Update() { 
    this.HandleTasks(); 
} 

void HandleTasks() 
{ 
    while (tasks.Count > 0) 
    { 
     Action task = null; 

     lock (tasks) 
     { 
      if (tasks.Count > 0) 
      { 
       task = tasks.Dequeue(); 
      } 
     } 

     task(); 
    } 
} 

public void QueueOnMainThread(Action task) 
{ 
    lock (tasks) 
    { 
     tasks.Enqueue(task); 
    } 
} 

private void StartClient() 
{ 
    try 
    { 
     IPAddress ipAddress = IPAddress.Parse("127.0.0.1"); 
     IPEndPoint remoteEP = new IPEndPoint(ipAddress, PORT_NUM); 

     Socket client = new Socket(AddressFamily.InterNetwork, 
      SocketType.Stream, ProtocolType.Tcp); 

     // Connect to the remote endpoint. 
     client.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), client); 
     connectDone.WaitOne(); 

     Receive(client); 
     receiveDone.WaitOne(); 

     Console.WriteLine("Response received : {0}", response); 

     // Release the socket 
     client.Shutdown(SocketShutdown.Both); 
     client.Close(); 
    } 
    catch (Exception e) 
    { 
     Debug.Log(e.ToString()); 
    } 
} 

private void ConnectCallback(IAsyncResult ar) 
{ 
    try 
    { 
     // Retrieve the socket from the state object. 
     Socket client = (Socket)ar.AsyncState; 

     // Complete the connection. 
     client.EndConnect(ar); 

     // Signal that the connection has been made. 
     connectDone.Set(); 
    } 
    catch (Exception e) 
    { 
     String error = e.ToString(); 
     Console.WriteLine(e.ToString()); 
     fnDisconnect(); 
    } 
} 

private void Receive(Socket client) 
{ 
    try 
    { 
     // Create the state object. 
     StateObject state = new StateObject(); 
     state.workSocket = client; 
     bytesRead = 0; 
     // Begin receiving the data from the remote device. 
     client.BeginReceive(state.buffer, bytesRead, StateObject.BufferSize, 0, 
      new AsyncCallback(ReceiveCallback), state); 
    } 
    catch (Exception e) 
    { 
     Console.WriteLine(e.ToString()); 
    } 
} 

private void ReceiveCallback(IAsyncResult ar) 
{ 
    try 
    { 
     // Retrieve the state object and the client socket 
     // from the asynchronous state object. 
     StateObject state = (StateObject)ar.AsyncState; 
     Socket client = state.workSocket; 

     // Read data from the remote device. 
     int numOfBytesRead = client.EndReceive(ar); 

     if (numOfBytesRead > 0) 
     { 
      bytesRead += numOfBytesRead; 
      if (bytesRead == StateObject.BufferSize) 
      { 
       this.QueueOnMainThread(() => 
       { 
        // All the data has arrived; put it in response. 
        ProcessFrame((byte[])state.buffer.Clone()); 
       }); 

       Receive(client); 
      } 
      else { 
       // Get the rest of the data. 
       client.BeginReceive(state.buffer, bytesRead, StateObject.BufferSize - bytesRead, 0, 
        new AsyncCallback(ReceiveCallback), state); 
      } 
     } 
     else 
     { 
      receiveDone.Set(); 
     } 

    } 
    catch (Exception e) 
    { 
     Console.WriteLine(e.ToString()); 
    } 
} 

代碼---數據處理

private void ProcessFrame(byte[] buffer) 
{ 

    byte[] bufferCopy = (byte[])buffer.Clone(); 

    double[,,] XYZArray = new double[IMGH, IMGW, 3]; 
    byte[,] DepthArray = new byte[IMGH, IMGW]; 
    byte[,,] RGBArray = new byte[IMGH, IMGW, 3]; 

    for (int i = 0; i < IMGW; i++) 
    { 
     for (int j = 0; j < IMGH; j++) 
     { 
      int index = (i * IMGW + j) * 20; 
      //byte[] arr = {bufferCopy[index], bufferCopy[index + 1], bufferCopy[index + 2], bufferCopy[index + 3] }; 
      float v = System.BitConverter.ToSingle(bufferCopy, index); 
      if (!float.IsInfinity(v) && !float.IsNaN(v)) 
      { 
       XYZArray[i, j, 0] = v; 
      } 
      //arr = new byte[]{bufferCopy[index + 4], bufferCopy[index + 5], bufferCopy[index + 6], bufferCopy[index + 7] }; 
      v = System.BitConverter.ToSingle(bufferCopy, index + 4); 
      if (!float.IsInfinity(v) && !float.IsNaN(v)) 
      { 
       XYZArray[i, j, 1] = v; 
      } 
      v = System.BitConverter.ToSingle(bufferCopy, index + 8); 
      if (!float.IsInfinity(v) && !float.IsNaN(v)) 
      { 
       XYZArray[i, j, 2] = v; 
      } 
      //       Debug.Log("for loop called"); 
      DepthArray[i, j] = bufferCopy[index + 12]; 
      RGBArray[i, j, 2] = bufferCopy[index + 16]; // B 
      RGBArray[i, j, 1] = bufferCopy[index + 17]; // G 
      RGBArray[i, j, 0] = bufferCopy[index + 18]; // R 
     } 
    } 
    this.EnQueue(XYZArray); 
} 

private void EnQueue(System.Object obj) 
{ 
    lock (queueLock) 
    { 
     queue.Enqueue(obj); 
    } 
} 

private bool DeQueue(System.Object outObj) 
{ 
    bool success = false; 
    lock (queueLock) 
    { 
     if (queue.Count > 0) 
     { 
      outObj = queue.Dequeue(); 
      success = true; 
     } 
    } 
    return success; 
} 

public int lengthOfQueue() 
{ 
    int count = -1; 
    lock (queueLock) 
    { 
     count = queue.Count; 
    } 
    return count; 
} 

public double[,,] getXYZArray() 
{ 
    double[,,] retVal = new double[,,] { }; 
    this.DeQueue(retVal); 
    return retVal; 
} 

UPDATE

感謝@Programmer的建議,我跟着他提供的鏈接有一個工作的套接字客戶端。

回答

1

整個代碼是一團糟。您應該使用Thread而不是Async來以較少的代碼完成該操作。

任何方式,與

byte[] bufferCopy = new byte[buffer.Length]; 
System.Buffer.BlockCopy(buffer, 0, bufferCopy, 0, bufferCopy.Length); 

而對於ProcessFrame((byte[])state.buffer.Clone());取代byte[] bufferCopy = (byte[])buffer.Clone();行代碼,簡單地傳遞數據而無需克隆它。所以應該用

ProcessFrame(state.buffer); 

這應該解決問題,假設這是你的代碼中唯一的問題。

編輯:

Here團結完整的TCP服務器代碼。將代碼移植到UDP,並且適用於您。

+0

感謝您的快速幫助。你能指出我正確的方式來使用'Thread'來處理Unity中的套接字連接嗎?非常感謝:) – dumbfingers

+0

@ ss1271在我這樣做之前,這是否解決了您的問題? – Programmer

+0

嗯實際上它仍在拖延......但你的建議是正確的做法,所以我跟着。 – dumbfingers