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

版权声明:原创文章如需转载,请在左侧博主描述栏目扫码联系我并取得授权,谢谢 https://blog.csdn.net/u012234115/article/details/46490351

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



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








阅读更多

扫码向博主提问

踏莎行hyx

支持是知识分享的动力,有问题可扫码哦
  • 擅长领域:
  • C++
  • scala
  • 游戏开发
  • 量化开发
  • 机器学习
去开通我的Chat快问
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页