Unityクライアントとサーバー通信【Unityネットワークプログラミング(4)】

1. Unity の UnityWebRequest クラス

UnityWebRequest は、HTTP リクエストを構成し、HTTP レスポンスを処理するためのモジュラー システムを提供します。UnityWebRequest システムの主な目的は、Unity ゲームが Web ブラウザー バックエンドと対話できるようにすることです。

1. HTTP トランザクションは、次の 3 つの異なる操作に分解されます。

  • サーバーにデータを提供する
  • サーバーからデータを受信する
  • HTTP フロー制御 (リダイレクトやエラー処理など)

2. 次のオブジェクトを管理できます。

  • UploadHandler オブジェクトは、サーバーへのデータ転送を処理します
  • DownloadHandler オブジェクトは、サーバーから受信したデータの受信、バッファリング、および後処理を処理します
  • UnityWebRequest このオブジェクトは、他の 2 つのオブジェクトを管理し、HTTP フロー制御も処理します。このオブジェクトは、カスタム ヘッダーと URL が定義される場所であり、エラーとリダイレクト情報が保存される場所です。

3. HTTP トランザクションの流れは次のとおりです。

  • Web 要求オブジェクトを作成する
  • Web 要求オブジェクトを構成する
    • カスタム ヘッダーを設定する
    • HTTP 動詞の設定 (GET、POST、HEAD など - Android を除くすべてのプラットフォームでカスタム動詞が許可されています)
    • URL の設定 * (オプション) アップロード ハンドラを作成し、それを Web リクエストに添付します
    • アップロードするデータを提供する
    • アップロードする HTTP フォームを指定します* (オプション) ダウンロード ハンドラーを作成し、それを 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 (Universal Code) 文字 (中国語を含む) のエンコード値を定義しますが、格納方法 (16 進数) を定義しません [たとえば、1 文字は 1 バイトですが、中国語も可能です。 4 バイトが必要]
UTF-8 は、ストレージに 1 ~ 6 バイトを使用できる可変長ソリューションである Unicode ストレージ メソッドを定義します。
UTF-16: UTF-8 と UTF-32 の間のソリューションで、ストレージに 2 バイトまたは 4 バイトを使用します
UTF-32: 固定の 4 バイトのストレージ方法、1 対 1 のエンコードで十分、シンプルですが、ストレージ効率は低すぎる
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 "登录成功"

おすすめ

転載: blog.csdn.net/cycler_725/article/details/127902189