C# 统一处理来自套接字的数据流 背景
我有一个简单的工作服务器,它从数据采集设备发送二进制数据,套接字连接工作,我的Unity客户端和其他客户端(如matlab客户端)都可以正确接收数据 然后Unity中的一个客户端尝试从该服务器接收数据,并将每个数据包中的字节分割成3D坐标数组 每个帧的大小应该是512x424像素,所以我需要等到数据填满512x424字节后再进行分割 问题 Unity在套接字连接和接收阶段正常运行,它将在处理阶段卡住(暂停):C# 统一处理来自套接字的数据流 背景,c#,sockets,unity3d,unity5,C#,Sockets,Unity3d,Unity5,我有一个简单的工作服务器,它从数据采集设备发送二进制数据,套接字连接工作,我的Unity客户端和其他客户端(如matlab客户端)都可以正确接收数据 然后Unity中的一个客户端尝试从该服务器接收数据,并将每个数据包中的字节分割成3D坐标数组 每个帧的大小应该是512x424像素,所以我需要等到数据填满512x424字节后再进行分割 问题 Unity在套接字连接和接收阶段正常运行,它将在处理阶段卡住(暂停):ProcessFrame((字节[])state.buffer.Clone()) 我读过
ProcessFrame((字节[])state.buffer.Clone())
我读过这篇文章:
并相应地更改了我的代码,但问题仍然存在
我做错什么了吗?谢谢你的帮助:)
代码-客户端
公共类SomeClass:monobhavior{
公共游戏对象领域;
常数int IMGW=512;
常数int IMGH=424;
常量int MAXBODY=6;
常数int NUMJOINT=25;
const int READ_BUFFER_SIZE=(4*3+4*1+4*1)*(IMGW*IMGH+MAXBODY*NUMJOINT);
const int PORT_NUM=20156;
公共字符串响应=string.Empty;
专用队列;
私有系统。对象队列锁;
私有int字节读;
//ManualResetEvent实例信号完成。
专用静态手动重置事件已完成=
新手动重置事件(错误);
私有静态手动重置事件sendDone=
新手动重置事件(错误);
私有静态手动重置事件接收完成=
新手动重置事件(错误);
//用于从远程设备接收数据的状态对象。
公共类状态对象
{
//客户端套接字。
公共套接字工作组=null;
//接收缓冲区。
public const int BufferSize=(4*3+4*1+4*1)*(IMGW*IMGH+MAXBODY*NUMJOINT);
公共字节[]缓冲区=新字节[BufferSize];
}
//我们使用它来保持在主线程中运行所需的任务
私有静态只读队列任务=新建队列();
//用于初始化
无效开始(){
queueLock=新对象();
队列=新队列();
this.StartClient();
//测试对象
sphere=GameObject.CreatePrimitive(PrimitiveType.sphere);
sphere.transform.position=新向量3(0,-1,10);
}
//每帧调用一次更新
无效更新(){
这个.HandleTasks();
}
void HandleTasks()
{
而(tasks.Count>0)
{
动作任务=null;
锁定(任务)
{
如果(tasks.Count>0)
{
task=tasks.Dequeue();
}
}
任务();
}
}
public void QueueOnMainThread(操作任务)
{
锁定(任务)
{
任务。排队(任务);
}
}
私有void StartClient()
{
尝试
{
IPAddress=IPAddress.Parse(“127.0.0.1”);
IPEndPoint remoteEP=新IPEndPoint(IP地址,端口号);
套接字客户端=新套接字(AddressFamily.InterNetwork,
流,ProtocolType.Tcp);
//连接到远程端点。
BeginConnect(remoteEP,新的异步回调(ConnectCallback),client);
connectDone.WaitOne();
接收(客户);
receiveDone.WaitOne();
WriteLine(“收到的响应:{0}”,响应);
//松开插座
client.Shutdown(SocketShutdown.Both);
client.Close();
}
捕获(例外e)
{
Log(例如ToString());
}
}
私有无效连接回调(IAsyncResult ar)
{
尝试
{
//从状态对象检索套接字。
套接字客户端=(套接字)ar.AsyncState;
//完成连接。
客户端.EndConnect(ar);
//表示已建立连接的信号。
connectDone.Set();
}
捕获(例外e)
{
字符串错误=e.ToString();
Console.WriteLine(如ToString());
fn断开连接();
}
}
私有void接收(套接字客户端)
{
尝试
{
//创建状态对象。
StateObject状态=新的StateObject();
state.workSocket=客户端;
字节读取=0;
//开始从远程设备接收数据。
client.BeginReceive(state.buffer、bytesRead、StateObject.BufferSize、0、,
新建异步回调(ReceiveCallback),状态);
}
捕获(例外e)
{
Console.WriteLine(如ToString());
}
}
私有void ReceiveCallback(IAsyncResult ar)
{
尝试
{
//检索状态对象和客户端套接字
//从异步状态对象。
StateObject状态=(StateObject)ar.AsyncState;
套接字客户端=state.workSocket;
//从远程设备读取数据。
int numobytesread=client.EndReceive(ar);
如果(numobytesread>0)
{
字节读取+=numobytesread;
if(bytesRead==StateObject.BufferSize)
{
this.QueueOnMainThread(()=>
{
//所有数据都已到达,请将其作为响应。
ProcessFrame((字节[])state.buffer.Clone());
});
接收(客户);
}
否则{
//获取其余的数据。
client.BeginReceive(state.buffer,bytesRead,StateObject.BufferSize-bytesRead,0,
新建异步回调(ReceiveCallback),状态);
}
}
其他的
{
receiveDone.Set();
}
}
捕获(例外e)
{
Console.WriteLine(如ToString());
}
}
代码——数据处理
private void ProcessFrame(字节[]缓冲区)
{
byte[]bufferCopy=(byte[])buffer.Clone();
double[,]XYZArray=新的双精度[IMGH,IMGW,3];
字节[,]DepthArray=新字节[IMGH,IMGW];
字节[,]RGBArray=新字节[IMGH,IMGW,3];
对于(int i=0;ipublic 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;
}
byte[] bufferCopy = new byte[buffer.Length];
System.Buffer.BlockCopy(buffer, 0, bufferCopy, 0, bufferCopy.Length);
ProcessFrame(state.buffer);