0%

hololens2的socket编程——TCP协议

解决方案网址:https://foxypanda.me/tcp-client-in-a-uwp-unity-app-on-hololens/
使用hololens2和PC端进行socket通讯的编程方法,其中前者是客户端而后者是服务器端。
这项任务实现有困难,根源在于hololens2的UWP和unity中运行的c#程序不兼容,一些库只能在unity中运行而不能在UWP中运行。
服务器端按照一般方式编写即可,不受影响。

接收服务器端消息的代码处有//TODO:这里的received就是接收到的信息
从而便于VS中查找(查找TODO的方法:先按下Ctrl+\,再按下T)

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.IO;
using System.Threading;
using System.Text;
using UnityEngine.UI;
using System.Threading.Tasks;


#if !UNITY_EDITOR
using System.Threading.Tasks;
#endif

public class TCPSocketScript : MonoBehaviour//hololens为客户端连接电脑
{
public string host;
public int port;
public string replyStr;
public static string textStr;
private bool firstReply = true;

[System.NonSerialized]
public static string[] textStrArray;

private Text tips;
#if !UNITY_EDITOR
private bool _useUWP = true;
private Windows.Networking.Sockets.StreamSocket socket;
private Task exchangeTask;
#endif

//笔记:
//这个是用来判断平台的语句。内部的内容只会在unity编辑器中执行。如果你打包了,他就不会被执行。
#if UNITY_EDITOR
private bool _useUWP = false;
System.Net.Sockets.TcpClient client;
System.Net.Sockets.NetworkStream stream;
private Thread exchangeThread;
private Text text;

#endif

private byte[] bytes = new byte[256];
private StreamWriter writer;
private StreamReader reader;

public static float needle_x;
public static float needle_y;
public static float needle_z;

public static float needle_q0;
public static float needle_qx;
public static float needle_qy;
public static float needle_qz;

public static float ribs339_x;
public static float ribs339_y;
public static float ribs339_z;

public static float ribs339_q0;
public static float ribs339_qx;
public static float ribs339_qy;
public static float ribs339_qz;

public static float probe340_x;
public static float probe340_y;
public static float probe340_z;

public static float probe340_q0;
public static float probe340_qx;
public static float probe340_qy;
public static float probe340_qz;

public static Quaternion needle_qua;
public static Quaternion ribs339_qua;
public static Quaternion probe340_qua;

public static Vector3 needle_posi;
public static Vector3 ribs339_posi;
public static Vector3 probe340_posi;

public static Matrix4x4 Tptmodel_ndi;//工具端
public static Matrix4x4 Tprobe_ndi;
public static Matrix4x4 T339_ndi;
public static Matrix4x4 Tndi_ptmodel;

public void Connect(string host, int port)
{

if (_useUWP)
{
ConnectUWP(host, port);
}
else
{
ConnectUnity(host, port);
}
}


#if UNITY_EDITOR
private void ConnectUWP(string host, int port)
#else
private async void ConnectUWP(string host, int port)
#endif

{
#if UNITY_EDITOR
print("UWP TCP clinet used in Unity!");
#else

try
{
//笔记:UWP,异步,TCP
if (exchangeTask != null) StopExchange();

socket = new Windows.Networking.Sockets.StreamSocket();
Windows.Networking.HostName serverHost = new Windows.Networking.HostName(host);
string portStr = Convert.ToString(port);

await socket.ConnectAsync(serverHost, portStr);

Stream streamOut = socket.OutputStream.AsStreamForWrite();
writer = new StreamWriter(streamOut) { AutoFlush = true };

Stream streamIn = socket.InputStream.AsStreamForRead();
reader = new StreamReader(streamIn);

RestartExchange();

}


catch (Exception e)
{
print("error"+e);
}
#endif
}

private void ConnectUnity(string host, int port)
{
#if !UNITY_EDITOR
print("Unity TCP client used in UWP!");

#else
try
{
if (exchangeThread != null) StopExchange();

client = new System.Net.Sockets.TcpClient(host, port);
stream = client.GetStream();
reader = new StreamReader(stream);
writer = new StreamWriter(stream) { AutoFlush = true };

RestartExchange();
print("Connected!");


}
catch (Exception e)
{
//TODO:
print("error" + e);
}

#endif
}


private bool exchanging = false;
private bool exchangeStopRequested = false;
private string lastPacket = null;



public void RestartExchange()
{
#if UNITY_EDITOR
//笔记:多线程
if (exchangeThread != null) StopExchange();
exchangeStopRequested = false;
exchangeThread = new System.Threading.Thread(ExchangePackets);

exchangeThread.Start();



#else
if (exchangeTask != null) StopExchange();
exchangeStopRequested = false;
exchangeTask = Task.Run(() => ExchangePackets());


#endif
}


public void ExchangePackets()
{
while (!exchangeStopRequested)
{
if (writer == null || reader == null) continue;
exchanging = true;

string received = "";
received = reader.ReadLine();//Server一定要发送有\n的内容!!
textStr = received;
print(received);
//TODO:这里的received就是接收到的信息
writer.Write(replyStr+"\n");
//Debug.Log("Sent data!");

#if UNITY_EDITOR
//byte[] bytes = new byte[client.SendBufferSize];
//int recv = 0;

//recv = stream.Read(bytes, 0, client.SendBufferSize);
//received += Encoding.UTF8.GetString(bytes, 0, recv);


#else
//笔记:读取发送来的信息
//TODO:没有接收到数据
//received = reader.ReadLine();


#endif

lastPacket = received;
// Debug.Log("Read data:" + received);
exchanging = false;

}

}



private void ReportDataToTrackingManager(string data)
{
if (data == null)
{
Debug.Log("Received a frame but data was null");
return;
}

if (firstReply == true)
{


//text.text = textStr;

firstReply = false;
}




//笔记:ndi发送的位姿数据
string[] ccc = data.Split(new string[] { "\t" }, StringSplitOptions.None);
int c_length = ccc.GetLength(0);
//print(c_length);

if (c_length > 0)
{
for (int i = 0; i < c_length; i++)
{
try
{
textStrArray[i] = ccc[i];
ReportStringToTrackingManager(ccc);
}

catch (Exception e)
{
Debug.Log(" ReportDataToTrackingManager" + e);

}

}
}
}

//NDI右手坐标系的四元数——Unity左手坐标系的四元数——左手坐标系的矩阵
//Quaternion ConvertToUnity(Quaternion input)
//{
// return new Quaternion(
// input.y, // -( right = -left )
// -input.z, // -( up = up )
// -input.x, // -(forward = forward)
// input.w
// );
//}

private void ReportStringToTrackingManager(string[] rigidBodyString)
{
//var ddd=rigidBodyString[].Split(new string[] { "," }, StringSplitOptions.None);
if (rigidBodyString.Length > 3)//过滤掉\n等字符
{
try
{
////肺部
//if (rigidBodyString[1+0*8] != "MISSING")
//{
// //转化成m
// ribs339_x = float.Parse(rigidBodyString[6 + 0 * 8]) / 1000;
// ribs339_y = float.Parse(rigidBodyString[7 + 0 * 8]) / 1000;
// ribs339_z = float.Parse(rigidBodyString[8 + 0 * 8]) / 1000;

// ribs339_q0 = float.Parse(rigidBodyString[2 + 0 * 8]);
// ribs339_qx = float.Parse(rigidBodyString[3 + 0 * 8]);
// ribs339_qy = float.Parse(rigidBodyString[4 + 0 * 8]);
// ribs339_qz = float.Parse(rigidBodyString[5 + 0 * 8]);

// ribs339_qua = new Quaternion(ribs339_qx, ribs339_qy, ribs339_qz, ribs339_q0).normalized;
// ribs339_posi = new Vector3(ribs339_x, ribs339_y, ribs339_z);
// T339_ndi = Matrix4x4.TRS(ribs339_posi, ribs339_qua, new Vector3(1, 1, 1));


// //T339_ndi
// //Vector3 trans_339 = ribs339_posi;
// //Quaternion qua_339 = ribs339_qua.normalized;


//}

//针
if (rigidBodyString[1 + 0 * 8] != "MISSING")
{
//转化成m
probe340_x = float.Parse(rigidBodyString[6 + 0 * 8]) / 1000;
probe340_y = float.Parse(rigidBodyString[7 + 0 * 8]) / 1000;
probe340_z = float.Parse(rigidBodyString[8 + 0 * 8]) / 1000;

probe340_q0 = float.Parse(rigidBodyString[2 + 0 * 8]);
probe340_qx = float.Parse(rigidBodyString[3 + 0 * 8]);
probe340_qy = float.Parse(rigidBodyString[4 + 0 * 8]);
probe340_qz = float.Parse(rigidBodyString[5 + 0 * 8]);

probe340_qua = new Quaternion(probe340_qx, probe340_qy, probe340_qz, probe340_q0).normalized;
probe340_posi = new Vector3(probe340_x, probe340_y, probe340_z);
Tprobe_ndi = Matrix4x4.TRS(probe340_posi,probe340_qua,new Vector3(1,1,1));

//Tprobe_ndi
//Vector3 trans_340 = probe340_posi;
//Quaternion qua_340 = probe340_qua.normalized;

}

//工具端
if (rigidBodyString[1 + 1 * 8] != "MISSING")
{

needle_x = float.Parse(rigidBodyString[6 + 1 * 8]) / 1000;
needle_y = float.Parse(rigidBodyString[7 + 1 * 8]) / 1000;
needle_z = float.Parse(rigidBodyString[8 + 1 * 8]) / 1000;

needle_q0 = float.Parse(rigidBodyString[2 + 1 * 8]);
needle_qx = float.Parse(rigidBodyString[3 + 1 * 8]);
needle_qy = float.Parse(rigidBodyString[4 + 1 * 8]);
needle_qz = float.Parse(rigidBodyString[5 + 1 * 8]);


needle_qua = new Quaternion(needle_qx, needle_qy, needle_qz, needle_q0).normalized;
needle_posi = new Vector3(needle_x, needle_y, needle_z);

// Tptmodel_ndi
//Vector3 trans_pt = needle_posi;
//Quaternion qua_pt = needle_qua.normalized;


//Tndi_ptmodel
Tptmodel_ndi = Matrix4x4.TRS(needle_posi, needle_qua, new Vector3(1, 1, 1));
Tndi_ptmodel = Tptmodel_ndi.inverse;

tips.text = needle_posi.x.ToString() + ","
+ needle_posi.y.ToString() + ","
+ needle_posi.z.ToString() + ","
+ needle_qua.w.ToString() + ","
+ needle_qua.x.ToString() + ","
+ needle_qua.y.ToString() + ","
+ needle_qua.z.ToString();

}


}
catch (Exception err)
{
Debug.Log("ReportStringToTrackingManager" + err.ToString());
}


}

}

public void StopExchange()
{
exchangeStopRequested = true;

#if UNITY_EDITOR
if (exchangeThread != null)
{
exchangeThread.Abort();
stream.Close();
client.Close();
writer.Close();
reader.Close();

stream = null;
exchangeThread = null;

}
#else
if (exchangeTask != null) {
exchangeTask.Wait();
socket.Dispose();
writer.Dispose();
reader.Dispose();

socket = null;
exchangeTask = null;
}
#endif
writer = null;
reader = null;
}



// Start is called before the first frame update
public void Start()
{
print("UDP!!!");
//tips = GameObject.Find("ModelTarget/PolarisProbe/Canvas/Text").GetComponent<Text>();
//string port = "26";
//string host = "192.168.3.10"; //连电脑的IP地址 SYBT
//string host = "10.135.217.20"; //连电脑的IP地址

//text = GameObject.Find("TextMeshPro11").GetComponent<Text>();
Connect(host, port);

}

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

//笔记:解析lastPacket
ReportDataToTrackingManager(lastPacket);
//tips = GameObject.Find("ModelTarget/PolarisProbe/Canvas/Text").GetComponent<Text>();

}

public void OnDestroy()
{
StopExchange();
}
}