Unity客户端和服务器通信【Unity网络编程(四)】

1.Unity的UnityWebRequest类

UnityWebRequest 提供了一个模块化系统,用于构成 HTTP 请求和处理 HTTP 响应。UnityWebRequest 系统的主要目标是让 Unity 游戏与 Web 浏览器后端进行交互。

1.HTTP 事务分解为三个不同的操作:

  • 向服务器提供数据
  • 从服务器接收数据
  • HTTP 流量控制(例如,重定向和错误处理)

2.可以管理下列对象:

  • UploadHandler 对象处理数据到服务器的传输
  • DownloadHandler 对象处理从服务器接收的数据的接收、缓冲和后处理
  • UnityWebRequest 对象管理其他两个对象,还处理 HTTP 流量控制。此对象是定义自定义标头和 URL 的位置,也是存储错误和重定向信息的位置。

3.一次HTTP 事务的流程如下:

  • 创建 Web 请求对象
  • 配置 Web 请求对象
    • 设置自定义标头
    • 设置 HTTP 动词(例如 GET、POST 和 HEAD - 除 Android 之外的所有平台都允许使用自定义动词)
    • 设置 URL *(可选)创建上传处理程序并将其附加到 Web 请求
    • 提供要上传的数据
    • 提供要上传的 HTTP 表单 *(可选)创建下载处理程序并将其附加到 Web 请求
  • 发送 Web 请求
    • 如果在协程中,可获得 Send() 调用的结果以等待请求完成 (可选)读取从下载处理程序接收的数据 (可选)从 UnityWebRequest 对象中读取错误信息、HTTP 状态码和响应标头

4.一次请求报文格式如下:

 5.返回状态码

通过www.responseCode,可以获取返回状态码:

 200表示正常

404大部分就是url写错了

500就大部分是服务器程序出错了

2.Unity客户端的代码实现:

1.登录功能实现(GET请求)

    public string url_base = "http://127.0.0.1:5566";
    public void Login(string username, string pwd)
    {
        StartCoroutine(login(username, pwd));
    }

    // 登录:"http://127.0.0.1:5566/login/?username=qwer&pwd=qwert"   
    IEnumerator login(string username, string password)
    {
        string url = url_base + "/login/?username=" + username + "&pwd=" + password;
        UnityWebRequest www = UnityWebRequest.Get(url);
        yield return www.SendWebRequest(); // 等待成功发送请求
        if (www.isNetworkError || www.isHttpError)
        {
            Debug.Log(www.error);
        }
        else
        {
            Debug.Log(www.downloadHandler.text); // 返回结果
        }
    }

2.发送数据功能实现(POST请求)

这里定义了数据库中每个表的类型,只要创建一个对象,就可以发送到服务器中

[Serializable]
    public class Insert<T>
    {
        public string tablename;
        public T datarow;// 需要插入的数据,只有一行
    }
    // 数据库中的一个表的类型
    [Serializable]
    public class users
    {
        public int id = 0;
        public string name = "";
        public int age = 0;
        public users() { }
        public users(int i, string n, int a)
        {
            id = i;
            name = n;
            age = a;
        }
    }

还需要进行字符串到字节的转换,这里记录一下不同字符类型的区别:

ASCII 0-255 1个字节,不包括中文
Unicode(万国码) 定义了字符的编码值(包括中文),但是不定义存储方式(几进制)【比如一个字母1个字节就行,但是中文又可能需要4个字节】
UTF-8 定义存储Unicode存储方式,是一种可变长度的方案,可使用1~6个字节存储。
UTF-16:介于 UTF-8 和 UTF-32 的方案,采用2字节或者4字节进行存储
UTF-32:一种固定的4个字节的存储方式,编码一一对应即可,简单但是存储效率太低
json:其实就是字符串,但是是键值对的形式


    //字符串格式转换为字节
    public static byte[] StringToBytes(string StringMessage)
    {
        //字符串转UTF-8 byte
        //string StringMessage = "Hello World How Are you? Pi /u03C0 Yen /uFFE5";
        System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding();
        return UTF8.GetBytes(StringMessage);
    }
    

3.实现建立请求和数据发送:

public string url_base = "http://127.0.0.1:5566";
    public void InsertData<T>(Insert<T> se)
    {
        StartCoroutine(Send_data<T>(se));
    }
    // 数据发送(表名、数据一行)
    IEnumerator Send_data<T>(Insert<T> Send)
    {
        string url = url_base + "/insert/";

        // 发送内容
        /*
         * {
         *  "tablename":"users",
         *  "datarow":{"id":60,"name":"test","age":123}   //每个类不一样
         *  }
         */

        string json_str = JsonUtility.ToJson(Send); // 转换成json格式
        byte[] byte_data = StringToBytes(json_str);// 转换成字节流形式

        print("发送" + json_str);

        // 通过上传handler发送字节数据
        UnityWebRequest www = new UnityWebRequest(url, "POST");
        www.uploadHandler = (UploadHandler)new UploadHandlerRaw(byte_data);     // 上传数据
        www.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer(); // 接收数据
        www.SetRequestHeader("Content-Type", "application/json"); //请求头 "application/x-www-form-urlencoded"
        print("数据请求状态码:" + www.responseCode);
        yield return www.SendWebRequest();

        if (www.isHttpError || www.isNetworkError)
        {
            Debug.LogError(www.error);
        }
        else
        {
            Debug.Log("data upload compelete:");
            Debug.Log(www.downloadHandler.text);
        }
    }

3.服务器代码的实现:

from flask import Flask,request,jsonify,make_response,json,redirect
from flask import request
app = Flask(__name__) 

@app.route('/login/', methods=["GET"])
def login():
    username = request.args.get('username')
    pwd = request.args.get('pwd')
    print("type:"+usertype)
    # 接收处理
    if username=='test' and pwd=='XXX'
        return "Success"
    return "Fail"

@app.route('/insert/',methods=['POST'])
def insert_data():
    print("插入,接收数据:",request.data)
    str_req = request.get_data(as_text=True)
    dic_data = json.loads(str_req) #转换为字典类型
    print(dic_data)
    # TODO:解析不同的数据,并且通过数据库返回不同数据
    return "Result"

if __name__=='__main__':
    print(app.url_map) # 打印url的路由映射
    app.run(host='127.0.0.1',port=5566,debug=False)

4.服务器对数据库进行处理

以登录请求为例子:

可以对函数进行封装,将服务器接收到的数据传递到此处进行处理,返回结果即可

from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column,Integer,String
from sqlalchemy.orm import sessionmaker
from sqlalchemy.orm import scoped_session
from sqlalchemy.dialects.mysql import INTEGER, DATETIME, REAL, TEXT, VARCHAR,BLOB
from sqlalchemy import Table, Column, ForeignKey, MetaData
from sqlalchemy.orm import mapper, sessionmaker
from sqlalchemy import  func

class UserLogin():
    def __init__(self) -> None:
        #连接数据库
        #初始化数据库连接# '数据库类型+数据库驱动名称://用户名:口令@机器地址:端口号/数据库名'
        self.url = sql_url
        engine = create_engine(self.url,encoding="utf-8",echo=False)
        #创建session类型
        DBSession = sessionmaker(bind=engine)
        #创建session对象
        self.session = DBSession()
    def login(self,username,pwd):
        sql_str = "SELECT * FROM account WHERE username='"+str(username) +"' and pwd='"+str(pwd)
        print(sql_str)
        try:
            cursor = self.session.execute(sql_str) 
            result = cursor.fetchall()
            if(len(result) == 0):
                return "登录失败"
        except Exception as e:
            print(e)
            return "登录失败!"
        return "登录成功"
  • 1
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值