unity开发:Qt C++与unity之间UDP网络通信

来源:互联网 发布:环境测试仪单片机包装 编辑:程序博客网 时间:2024/05/29 13:10

再试试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_OBJECTpublic:    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);}

main.cpp未更改,不贴了


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旋转








0 0
原创粉丝点击