web-dev-qa-db-fra.com

Comment se connecter à la base de données à partir d'Unity

J'essaie de me connecter à une base de données MS SQL via Unity. Cependant, lorsque j'essaie d'ouvrir une connexion, j'obtiens une exception IOException: Connexion perdue.

J'ai importé System.Data.dll de Unity\Editor\Data\Mono\lib\mono\2.0. J'utilise le code suivant:

 using UnityEngine;
 using System.Collections;
 using System.Data.Sql;
 using System.Data.SqlClient;

 public class SQL_Controller : MonoBehaviour {

     string conString = "Server=myaddress.com,port;" +
             "Database=databasename;" +
             "User ID=username;" +
             "Password=password;";

     public string GetStringFromSQL()
     {
         LoadConfig();
         string result = "";

         SqlConnection connection = new SqlConnection(conString);
         connection.Open();
         Debug.Log(connection.State);
         SqlCommand Command = connection.CreateCommand();
         Command.CommandText = "select * from Artykuly2";
         SqlDataReader ThisReader = Command.ExecuteReader();
         while (ThisReader.Read())
         {
             result = ThisReader.GetString(0);
         }
         ThisReader.Close();
         connection.Close();

         return result;
     }
 }

C'est l'erreur que j'obtiens:

IOException: Connection lost
Mono.Data.Tds.Protocol.TdsComm.GetPhysicalPacketHeader ()
Mono.Data.Tds.Protocol.TdsComm.GetPhysicalPacket ()
Mono.Data.Tds.Protocol.TdsComm.GetByte ()
Mono.Data.Tds.Protocol.Tds.ProcessSubPacket ()
Mono.Data.Tds.Protocol.Tds.NextResult ()
Mono.Data.Tds.Protocol.Tds.SkipToEnd ()
Rethrow as TdsInternalException: Server closed the connection.
Mono.Data.Tds.Protocol.Tds.SkipToEnd ()
Mono.Data.Tds.Protocol.Tds70.Connect (Mono.Data.Tds.Protocol.TdsConnectionParameters connectionParameters)
Mono.Data.Tds.Protocol.Tds80.Connect (Mono.Data.Tds.Protocol.TdsConnectionParameters connectionParameters)

Ne tenez pas compte des risques pour la sécurité avec cette approche, j’ai BESOIN de le faire pour les tests, la sécurité viendra plus tard ... Merci de votre temps.

6
MLazowski

Veuillez ignorer les risques de sécurité avec cette approche

Ne le fais pas comme ça. Peu importe que la sécurité vienne avant ou après. Vous finirez par réécrire tout le code car le mot de passe est codé en dur dans votre application. Il peut être décompilé et récupéré facilement. Faites la connexion correctement maintenant pour ne pas avoir à ré-écrire toute l'application. 

Exécutez votre commande de base de données sur votre serveur avec php, Perl ou toute autre langue avec laquelle vous êtes à l'aise, mais cela devrait être fait sur le serveur.

À partir de Unity, utilisez la classe WWW ou UnityWebRequest / pour communiquer avec ce script. Vous pourrez ensuite envoyer et recevoir des informations de Unity au serveur. Il y a beaucoup exemples out there . Même avec cela, vous devez toujours mettre en œuvre votre propre sécurité, mais c'est beaucoup mieux que ce que vous avez maintenant.

Vous pouvez également recevoir plusieurs données avec json

Vous trouverez ci-dessous un exemple complet tiré de this Unity wiki. Il montre comment interagir avec une base de données dans Unity en utilisant php côté serveur et Unity + C # côté client.

Du côté serveur:

_ {Ajouter le score avec PDO} _:

<?php
        // Configuration
        $hostname = 'localhot';
        $username = 'yourusername';
        $password = 'yourpassword';
        $database = 'yourdatabase';

        $secretKey = "mySecretKey"; // Change this value to match the value stored in the client javascript below 

        try {
            $dbh = new PDO('mysql:Host='. $hostname .';dbname='. $database, $username, $password);
        } catch(PDOException $e) {
            echo '<h1>An error has ocurred.</h1><pre>', $e->getMessage() ,'</pre>';
        }

        $realHash = md5($_GET['name'] . $_GET['score'] . $secretKey); 
        if($realHash == $hash) { 
            $sth = $dbh->prepare('INSERT INTO scores VALUES (null, :name, :score)');
            try {
                $sth->execute($_GET);
            } catch(Exception $e) {
                echo '<h1>An error has ocurred.</h1><pre>', $e->getMessage() ,'</pre>';
            }
        } 
?>

Récupérer le score avec PDO:

<?php
    // Configuration
    $hostname = 'localhost';
    $username = 'yourusername';
    $password = 'yourpassword';
    $database = 'yourdatabase';

    try {
        $dbh = new PDO('mysql:Host='. $hostname .';dbname='. $database, $username, $password);
    } catch(PDOException $e) {
        echo '<h1>An error has occurred.</h1><pre>', $e->getMessage() ,'</pre>';
    }

    $sth = $dbh->query('SELECT * FROM scores ORDER BY score DESC LIMIT 5');
    $sth->setFetchMode(PDO::FETCH_ASSOC);

    $result = $sth->fetchAll();

    if(count($result) > 0) {
        foreach($result as $r) {
            echo $r['name'], "\t", $r['score'], "\n";
        }
    }
?>

Activer la politique interdomaine sur le serveur:

Ce fichier doit être nommé "crossdomain.xml" et placé à la racine de votre serveur Web. Unity exige que les sites Web auxquels vous souhaitez accéder via une requête WWW aient une stratégie interdomaine.

<?xml version="1.0"?>
<cross-domain-policy>
<allow-access-from domain="*"/>
</cross-domain-policy>

Client/Unity Side:

Le code client d'Unity se connecte au serveur, interagit avec PDO et ajoute ou récupère le score en fonction de la fonction appelée. Ce code client est légèrement modifié pour être compilé avec la dernière version de Unity.

private string secretKey = "mySecretKey"; // Edit this value and make sure it's the same as the one stored on the server
public string addScoreURL = "http://localhost/unity_test/addscore.php?"; //be sure to add a ? to your url
public string highscoreURL = "http://localhost/unity_test/display.php";

//Text to display the result on
public Text statusText;

void Start()
{
    StartCoroutine(GetScores());
}

// remember to use StartCoroutine when calling this function!
IEnumerator PostScores(string name, int score)
{
    //This connects to a server side php script that will add the name and score to a MySQL DB.
    // Supply it with a string representing the players name and the players score.
    string hash = Md5Sum(name + score + secretKey);

    string post_url = addScoreURL + "name=" + WWW.EscapeURL(name) + "&score=" + score + "&hash=" + hash;

    // Post the URL to the site and create a download object to get the result.
    WWW hs_post = new WWW(post_url);
    yield return hs_post; // Wait until the download is done

    if (hs_post.error != null)
    {
        print("There was an error posting the high score: " + hs_post.error);
    }
}

// Get the scores from the MySQL DB to display in a GUIText.
// remember to use StartCoroutine when calling this function!
IEnumerator GetScores()
{
    statusText.text = "Loading Scores";
    WWW hs_get = new WWW(highscoreURL);
    yield return hs_get;

    if (hs_get.error != null)
    {
        print("There was an error getting the high score: " + hs_get.error);
    }
    else
    {
        statusText.text = hs_get.text; // this is a GUIText that will display the scores in game.
    }
}

public string Md5Sum(string strToEncrypt)
{
    System.Text.UTF8Encoding ue = new System.Text.UTF8Encoding();
    byte[] bytes = ue.GetBytes(strToEncrypt);

    // encrypt bytes
    System.Security.Cryptography.MD5CryptoServiceProvider md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
    byte[] hashBytes = md5.ComputeHash(bytes);

    // Convert the encrypted bytes back to a string (base 16)
    string hashString = "";

    for (int i = 0; i < hashBytes.Length; i++)
    {
        hashString += System.Convert.ToString(hashBytes[i], 16).PadLeft(2, '0');
    }

    return hashString.PadLeft(32, '0');
}

Ceci est juste un exemple sur la façon de le faire correctement. Si vous devez implémenter la fonctionnalité de session et vous préoccuper de la sécurité, examinez le protocole OAuth 2.0. Il devrait exister des bibliothèques existantes qui vous aideront à démarrer avec le protocole OAuth

8
Programmer

Une alternative serait de créer votre propre serveur dédié dans une invite de commande pour effectuer votre communication et le connecter à l'unité à la communication multijoueur et SQL de Handel. De cette façon, vous pouvez vous en tenir à ce que tout soit créé dans une seule langue. Mais une courbe d'apprentissage assez raide.

1
Jason