ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

HoloLens中基于Socket的TCP通信系统

HoloLens中基于Socket的TCP通信系统 HoloLens中基于Socket的TCP通信系统系统目标服务器端客户端测试与使用系统目标实现服务器端PC与客户端HoloLens通信。PC向HoloLens发送数据HoloLens接收到数据后向PC发送消息确认。服务器端将下面代码挂在Unity场景中,该场景做为服务器。usingSystem.Collections;usingSystem.Collections.Generic;usingSystem;usingSystem.IO;usingUnityEngine;usingSystem.Net;usingSystem.Net.Sockets;usingSystem.Text;usingSystem.Threading;publicclassServer:MonoBehaviour{ListSocketClientProxSocketListnewListSocket();stringeditString编辑发送内容;//编辑框文字//定义服务器的IP和端口端口与服务器对应publicstringIPAddress_Server10.175.46.8;//可以是局域网或互联网ippublicstringPort_Server5000;// Start is called before the first frame updatevoidStart(){}voidOnGUI(){IPAddress_ServerGUI.TextField(newRect(10,10,100,20),IPAddress_Server);Port_ServerGUI.TextField(newRect(120,10,60,20),Port_Server);if(GUI.Button(newRect(200,10,100,20),启动服务器))ServerStart();editStringGUI.TextField(newRect(10,40,150,20),editString);if(GUI.Button(newRect(180,40,100,20),发送字符串))SendMsg();}// Update is called once per framevoidUpdate(){}privatevoidServerStart(){//1 创建Socket对象SocketsocketnewSocket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);//2 绑定端口ipsocket.Bind(newIPEndPoint(IPAddress.Parse(IPAddress_Server),int.Parse(Port_Server)));//3 开启侦听socket.Listen(10);//链接等待队列同时来了100个链接请求队列里放10个等待链接客户端其他返回错误信息//4 开始接受客户端的链接ThreadPool.QueueUserWorkItem(newWaitCallback(this.AcceptClientConnect),socket);}publicvoidAcceptClientConnect(objectsocket){varserverSocketsocketasSocket;//强制类型转换this.AppendTextToConsole(服务器端开始接受客户端的链接);while(true)//不断的接收{varproxSocketserverSocket.Accept();//会阻塞当前线程因此必须放入异步线程池中this.AppendTextToConsole(string.Format(客户端:{0}链接上了,proxSocket.RemoteEndPoint.ToString()));ClientProxSocketList.Add(proxSocket);//使方法体外部也可以访问到方法体内部的数据//不停接收当前链接的客户端发送来的消息//不能因为接收一个客户端消息阻塞整个线程启用线程池ThreadPool.QueueUserWorkItem(newWaitCallback(this.ReceiveData),proxSocket);}}//接收客户端消息publicvoidReceiveData(objectsocket){varproxSocketsocketasSocket;byte[]datanewbyte[1024*1024];while(true){intlen0;try{lenproxSocket.Receive(data,0,data.Length,SocketFlags.None);}catch(Exceptionex){//异常退出,在阻塞线程时与服务器连接中断或断电等等AppendTextToConsole(string.Format(接收到客户端:{0}非正常退出,proxSocket.RemoteEndPoint.ToString()));ClientProxSocketList.Remove(proxSocket);StopConnect(proxSocket);return;}if(len0){//客户端正常退出AppendTextToConsole(string.Format(接收到客户端:{0}正常退出,proxSocket.RemoteEndPoint.ToString()));ClientProxSocketList.Remove(proxSocket);StopConnect(proxSocket);return;//让方法结束。终结当前接收客户端数据的异步线程}//把接收到的数据放到文本框上stringstrEncoding.Default.GetString(data,0,len);AppendTextToConsole(string.Format(接收到客户端:{0}的消息是:{1},proxSocket.RemoteEndPoint.ToString(),str));}}privatevoidStopConnect(SocketproxSocket){try{if(proxSocket.Connected){proxSocket.Shutdown(SocketShutdown.Both);proxSocket.Close(100);//100秒后没有正常关闭则强行关闭}}catch(Exceptionex){}}//发送字符串privatevoidSendMsg(){foreach(varproxSocketinClientProxSocketList){if(proxSocket.Connected){//原始的字符串转换成的字节数组byte[]dataEncoding.Default.GetBytes(editString);proxSocket.Send(data,0,data.Length,SocketFlags.None);}}}//在控制台打印要显示的内容publicvoidAppendTextToConsole(stringtxt){Debug.Log(string.Format({0},txt));}}客户端将下面代码挂在Unity的另一个场景中该场景做为客户端。usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;usingSystem;usingSystem.Linq;usingSystem.Net;usingSystem.Net.Sockets;usingSystem.Text;usingSystem.Threading;usingSystem.Threading.Tasks;usingSystem.IO;publicclassSAEA:MonoBehaviour{publicSocketm_socket;IPEndPointm_endPoint;privateSocketAsyncEventArgsm_connectSAEA;privateSocketAsyncEventArgsm_sendSAEA;publicstaticstringip10.175.46.8;publicintport5000;privatevoidStart(){Client();}publicvoidClient(){m_socketnewSocket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);IPAddressiPAddressIPAddress.Parse(ip);m_endPointnewIPEndPoint(iPAddress,port);m_connectSAEAnewSocketAsyncEventArgs{RemoteEndPointm_endPoint};m_connectSAEA.CompletednewEventHandlerSocketAsyncEventArgs(OnConnectedCompleted);m_socket.ConnectAsync(m_connectSAEA);}stringipAdress;//连接远程的ip地址intlengthBuffer;//缓冲区长度byte[]receiveBuffer;//接收缓冲区voidOnConnectedCompleted(objectsender,SocketAsyncEventArgse){if(e.SocketError!SocketError.Success)return;SocketsocketsenderasSocket;stringiPRemotesocket.RemoteEndPoint.ToString();Debug.Log(Client : 连接服务器iPRemote成功);SocketAsyncEventArgsreceiveSAEAnewSocketAsyncEventArgs();byte[]receiveBuffernewbyte[1024*1024*16];receiveSAEA.SetBuffer(receiveBuffer,0,receiveBuffer.Length);receiveSAEA.CompletedOnReceiveCompleted;receiveSAEA.RemoteEndPointm_endPoint;socket.ReceiveAsync(receiveSAEA);}voidOnReceiveCompleted(objectsender,SocketAsyncEventArgse){if(e.SocketErrorSocketError.OperationAborted)return;SocketsocketsenderasSocket;if(e.SocketErrorSocketError.Successe.BytesTransferred0){ipAdresssocket.RemoteEndPoint.ToString();lengthBuffere.BytesTransferred;receiveBuffere.Buffer;//向服务器端发送消息Send(成功收到消息);socket.ReceiveAsync(e);}elseif(e.SocketErrorSocketError.ConnectionResete.BytesTransferred0){Debug.Log(Client: 服务器断开连接 );}else{return;}}#region发送publicvoidSend(stringmsg){byte[]sendBufferEncoding.Default.GetBytes(msg);if(m_sendSAEAnull){m_sendSAEAnewSocketAsyncEventArgs();m_sendSAEA.CompletedOnSendCompleted;}m_sendSAEA.SetBuffer(sendBuffer,0,sendBuffer.Length);if(m_socket!null){m_socket.SendAsync(m_sendSAEA);}}privatevoidOnSendCompleted(objectsender,SocketAsyncEventArgse){if(e.SocketError!SocketError.Success)return;SocketsocketsenderasSocket;byte[]sendBuffere.Buffer;stringsendMsgEncoding.Default.GetString(sendBuffer);Debug.Log(Client : Send messagesendMsgto Serersocket.RemoteEndPoint.ToString());}#endregion#region断开连接publicvoidDisConnect(){if(m_socket!null){try{m_socket.Shutdown(SocketShutdown.Both);}catch(SocketExceptione){}finally{m_socket.Close();}}}#endregion}将客户端场景打包生成UWP应用Player Setting如下Capabilities设置如下测试与使用在Unity中启动服务器端设置ip和port启动服务器。在HoloLens中运行之前打包生成的客户端UWP与服务器进行连接控制台消息如下注意如果在HoloLens中出现错误错误“ArgumentException: Value does not fall within the expected range”请参考在Hololens中开发TCP通信错误“ArgumentException: Value does not fall within the expected range”的解决方案。这是Unity更新版本Socket出问题所导致的
返回列表