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 "登录成功"