再试试UDP通信,发送速度快,更加灵活
UDP实际相当于是对等通信,不用建立连接,但是这里为了有个server的概念,在服务端绑定了端口,而客户端则是发送时随机分配的端口
Qt C++服务端
建立gui工程,pro里面加入network模块,界面放一个label,两个button
widget.h
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QUdpSocket> namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); private: Ui::Widget *ui; private: QString statusText; //状态信息 QUdpSocket *udpSocket; //套接字 QHostAddress clientIp; //客户端ip quint16 clientPort; //客户端port void SocketSend(QString sendStr,QHostAddress targetIp,quint16 targetPort); //发送数据,可以向指定目标发送,或者广播 private slots: void ProcessPendingDatagram(); //当接收到数据时作出响应 void on_leftBtn_clicked(); void on_rightBtn_clicked(); }; #endif // WIDGET_H
widget.cpp
#include "widget.h" #include "ui_widget.h" Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); //初始化udp udpSocket=new QUdpSocket(this); udpSocket->bind(QHostAddress::Any,8888);//绑定ip和端口,可以是Any,LocalHost //label显示状态 statusText=statusText+"wait for connecting..."+"\n"; ui->statusLabel->setText(statusText); //绑定信号槽,当接收到数据时作出反应 connect(udpSocket,SIGNAL(readyRead()),this,SLOT(ProcessPendingDatagram())); } void Widget::ProcessPendingDatagram() { //等待数据接收完毕再做处理 while(udpSocket->hasPendingDatagrams()) { QByteArray recvData; recvData.resize(udpSocket->pendingDatagramSize()); udpSocket->readDatagram(recvData.data(),recvData.size(),&clientIp,&clientPort); //从发送方的包中读取数据以及ip和port并赋值给类的变量 statusText+="connet from "+clientIp.toString()+":"+QString::number(clientPort)+" "; statusText+=recvData+"\n"; //显示到状态标签 ui->statusLabel->setText(statusText); //转发回去 SocketSend("from server:"+recvData,clientIp,clientPort); } } void Widget::SocketSend(QString sendStr,QHostAddress targetIp,quint16 targetPort) { udpSocket->writeDatagram(sendStr.toStdString().c_str(),sendStr.length(),targetIp,targetPort); } Widget::~Widget() { delete ui; } //unity物体左旋 void Widget::on_leftBtn_clicked() { SocketSend("leftrotate",clientIp,clientPort); } //unity物体右旋 void Widget::on_rightBtn_clicked() { SocketSend("rightrotate",clientIp,clientPort); }
unity C#客户端
同样是吧udp socket部分封装成了一个类,加到另外一个类里面,挂到场景里
UdpClientHandler.cs
using UnityEngine; using System.Collections; //引入库 using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; public class UdpClientHandler:MonoBehaviour { //以下默认都是私有的成员 Socket socket; //目标socket EndPoint serverEnd; //服务端 IPEndPoint ipEnd; //服务端端口 string recvStr; //接收的字符串 string sendStr; //发送的字符串 byte[] recvData=new byte[1024]; //接收的数据,必须为字节 byte[] sendData=new byte[1024]; //发送的数据,必须为字节 int recvLen; //接收的数据长度 Thread connectThread; //连接线程 //初始化 public void InitSocket() { //定义连接的服务器ip和端口,可以是本机ip,局域网,互联网 ipEnd=new IPEndPoint(IPAddress.Parse("127.0.0.1"),8888); //定义套接字类型,在主线程中定义 socket=new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp); //定义服务端 IPEndPoint sender=new IPEndPoint(IPAddress.Any,0); serverEnd=(EndPoint)sender; print("waiting for sending UDP dgram"); //建立初始连接,这句非常重要,第一次连接初始化了serverEnd后面才能收到消息 SocketSend("hello"); //开启一个线程连接,必须的,否则主线程卡死 connectThread=new Thread(new ThreadStart(SocketReceive)); connectThread.Start(); } public void SocketSend(string sendStr) { //清空发送缓存 sendData=new byte[1024]; //数据类型转换 sendData=Encoding.ASCII.GetBytes(sendStr); //发送给指定服务端 socket.SendTo(sendData,sendData.Length,SocketFlags.None,ipEnd); } //服务器接收 void SocketReceive() { //进入接收循环 while(true) { //对data清零 recvData=new byte[1024]; //获取客户端,获取服务端端数据,用引用给服务端赋值,实际上服务端已经定义好并不需要赋值 recvLen=socket.ReceiveFrom(recvData,ref serverEnd); print("message from: "+serverEnd.ToString()); //打印服务端信息 //输出接收到的数据 recvStr=Encoding.ASCII.GetString(recvData,0,recvLen); print(recvStr); } } //返回接收到的字符串 public string GetRecvStr() { string returnStr; //加锁防止字符串被改 lock(this) { returnStr=recvStr; } return returnStr; } //连接关闭 public void SocketQuit() { //关闭线程 if(connectThread!=null) { connectThread.Interrupt(); connectThread.Abort(); } //最后关闭socket if(socket!=null) socket.Close(); } }UdpTest.cs
using UnityEngine; using System.Collections; public class UdpTest:MonoBehaviour { string editString="hello wolrd"; //编辑框文字 GameObject cube; UdpClientHandler udpClient; // Use this for initialization void Start() { //初始化网络 udpClient=gameObject.AddComponent<UdpClientHandler>(); udpClient.InitSocket(); //找到cube cube=GameObject.Find("Cube"); } void OnGUI() { editString=GUI.TextField(new Rect(10,10,100,20),editString); GUI.Label(new Rect(10,30,300,20),udpClient.GetRecvStr()); if(GUI.Button(new Rect(10,50,60,20),"send")) udpClient.SocketSend(editString); } // Update is called once per frame void Update() { if(udpClient.GetRecvStr()!=null) { switch(udpClient.GetRecvStr()) { case "leftrotate": cube.transform.Rotate(Vector3.up,50*Time.deltaTime); break; case "rightrotate": cube.transform.Rotate(Vector3.down,50*Time.deltaTime); break; } } } void OnApplicationQuit() { //退出时关闭连接 udpClient.SocketQuit(); } }
依然是服务端和客户端之间互相收发消息,服务端可以控制客户端里面的cube旋转