Unity - saving simple data off device [duplicate] - c#

I am trying to connect to a MS SQL database through Unity. However, when I try to open a connection, I get an IOException: Connection lost.
I have imported System.Data.dll from Unity\Editor\Data\Mono\lib\mono\2.0. I am using the following code:
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;
}
}
This is the error I get:
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)
Please disregard any security risks with this approach, I NEED to do this for testing, security will come later.
Thank you for your time.

Please disregard any security risks with this approach
Do not do it like this. It doesn't matter if security will come before or after. You will end of re-writing the whole code because the password is hard-coded in your application which can be decompiled and retrieved easily. Do the connection the correct way now so that you won't have to re-write the whole application.
Run your database command on your server with php, perl or whatever language you are comfortable with but this should be done on the server.
From Unity, use the WWW or UnityWebRequest class to communicate with that script and then, you will be able to send and receive information from Unity to the server. There are many examples out there. Even with this, you still need to implement your own security but this is much more better than what you have now.
You can also receive data multiple with json.
Below is a complete example from this Unity wiki. It shows how to interact with a database in Unity using php on the server side and Unity + C# on the client side.
Server Side:
Add score with 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>';
}
}
?>
Retrieve score with 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";
}
}
?>
Enable cross domain policy on the server:
This file should be named "crossdomain.xml" and placed in the root of your web server. Unity requires that websites you want to access via a WWW Request have a cross domain policy.
<?xml version="1.0"?>
<cross-domain-policy>
<allow-access-from domain="*"/>
</cross-domain-policy>
Client/Unity Side:
The client code from Unity connects to the server, interacts with PDO and adds or retrieves score depending on which function is called. This client code is slightly modified to compile with the latest Unity version.
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');
}
This is just an example on how to properly do this. If you need to implement session feature and care about security, look into the OAuth 2.0 protocol. There should be existing libraries that will help get started with the OAuth protocol.

An alternative would be to create your own dedicated server in a command prompt to do your communication and connecting it to unity to Handel multiplayer and SQL communication. This way you can stick with it all being created in one language. But a pretty steep learning curve.

Unity is game engine.
so That's right what the answer says.
but, Some domains need to connect database directly.
You shouldn't do that access database directly in game domain.
Anyway, The problem is caused by NON-ENGLISH computer name.
I faced sort of following errors at before project.
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)
And after changing computer name as ENGLISH, It works.
I don't know how it's going. But It works.
Mono's System.Data.dll has some issues in P.C has NON-ENGLISH Computer name.
So, at least Unity project.
You should tell your customer Do not set their computer name as NON-ENGLISH.
I don't know people in mono knows these issue or not.
---------- It's OK in after 2018 version ----------
Api Compatibility Level > .Net 4.x
You can connect database in Non-english computer name machine.

Related

XAMPP becomes super slow after some time

Does anyone ever encounter the MYSQL in XAMPP being super slow after sometime?
I have a unity application that asking a string to be downloaded with this php script.
<?php
include 'Config.php'; // Just a normal mysqli connection setup
//the post from Unity.
$var_uniqueID = $_POST['uniqueID_Post'];
$conn = OpenCon(); // open connection
//create a query
$sql = "SELECT
var_name,
var_value
FROM variable_current_values
WHERE uniqueID = '".$var_uniqueID."' ";
$result = mysqli_query($conn, $sql);
if( mysqli_num_rows($result) > 0)
{
//show data for each row
while($row = mysqli_fetch_assoc($result))
{
echo "".$row['var_name'] .
"|".$row['var_value'] . "";
}
}
CloseCon($conn); // close the connection
?>
This PHP script is being called with c# script of UnityWebRequest
//www variable
private UnityWebRequest unityWebRequest;
void Update ()
{
if (unityWebRequest == null)
{
//fetch The data Widget
StartCoroutine(RealDataFetchWhere(this.name));
}
}
private IEnumerator RealDataFetchWhere(string _uniqueIDPost)
{
//gives the unique key
WWWForm fetchingForm = new WWWForm();
fetchingForm.AddField("uniqueID_Post", _uniqueIDPost);
//load and wait until the data is downloaded
unityWebRequest = UnityWebRequest.Post(**thePHPLink**, fetchingForm);
yield return unityWebRequest.SendWebRequest();
string data = unityWebRequest.downloadHandler.text;
print("the Data is : " + data);
}
At first everything seems to be fine. Data is downloaded perfectly(almost in realtime speed).
However after like more than 10 minutes, the XAMPP mySQL starting to slow down considerably. I try to modified the data manually in XAMPP and it takes about 5 - 8 seconds until the "row is affected"
If i leave them longer without closing my unity program, XAMPP start to freeze and disconnected.
Does anyone know the solutions to counter this problem ?

How can I connect to a Bluetooth service on Gear S3?

I am writing a web app for the Gear S3 and a companion Win-App for UWP in C#.
What I want it to do: S3 acting as a BT server, sending data, and the Win-App as a client, which is supposed to receive the data.
In Tizen I used the registerRfcommServiceByUUID() function as below:
function publishTransferService() {
if(remoteDevice.isConnented){
console.log("Connection Status: " + remoteDevice.isConnected);
var TRANS_SERVICE_UUID = '5BCE9431-6C75-32AB-AFE0-2EC108A30860';
adapter.registerRFCOMMServiceByUUID(TRANS_SERVICE_UUID, 'My Service', ServiceSuccessCb,
function(e) {
console.log( "Could not register service record, Error: " + e.message);
});
}else{
console.error("Connection Status: " + remoteDevice.isConnected);
}
In C# i try to connect to the service as follows:
//to ulong converted MAC-Address of the Gear
ulong gearBtAddress = 145914022804881;
//create device-instance of the gear
BluetoothDevice gearDevice = await BluetoothDevice.FromBluetoothAddressAsync(gearBtAddress);
//list the services found on the gear and connect to the one with
//the same uuid as in tizen
var gearServices = await gearDevice.GetRfcommServicesAsync();
foreach (var service in gearServices.Services)
{
if(service.ServiceId == RfcommServiceId.FromUuid(Guid.Parse("5BCE9431-6C75-32AB-AFE0-2EC108A30860")))
{
_service = await RfcommDeviceService.FromIdAsync(service.ToString());
}
}
The Problem I am facing is, that the C# won't find the wanted Uuid, although it finds several other uuids. I don't see where it gets lost?
Thanks in advance.
I solved it myself, the problem was, that the UUID was uncached. Adding the following was all to do:
var cacheMode = BluetoothCacheMode.Uncached;
var gearServices = await gearDevice.GetRfcommServicesAsync(cacheMode);

-ERR Exceeded the login limit for a 15 minute period. Reduce the frequency of requests to the POP3 server

using following code i have reading msg from my hotmail account . But sometimes the following error coming . -ERR Exceeded the login limit for a 15 minute period. Reduce the frequency of requests to the POP3 server . can anyone tell me whats the reason for this ? Is that server problem or anything else ? other than pop3 anyother protocol can we use for hotmail?
public string hotmail(string username, string password)
{
string result = "";
string str = string.Empty;
string strTemp = string.Empty;
try
{
TcpClient tcpclient = new TcpClient();
tcpclient.Connect("pop3.live.com", 995);
System.Net.Security.SslStream sslstream = new SslStream(tcpclient.GetStream());
sslstream.AuthenticateAsClient("pop3.live.com");
System.IO.StreamWriter sw = new StreamWriter(sslstream);
System.IO.StreamReader reader = new StreamReader(sslstream);
strTemp = reader.ReadLine();
sw.WriteLine("USER" + " " + username);
sw.Flush();
strTemp = reader.ReadLine();
sw.WriteLine("PASS" + " " + password);
sw.Flush();
strTemp = reader.ReadLine();
string[] numbers = Regex.Split(strTemp, #"\D+");
int a = 0;
foreach (string value in numbers)
{
if (!string.IsNullOrEmpty(value))
{
int i = int.Parse(value);
numbers[a] = i.ToString();
a++;
}
}
sw.WriteLine("RETR" + " " + numbers[0]);
sw.Flush();
strTemp = reader.ReadLine();
while ((strTemp = reader.ReadLine()) != null)
{
if (strTemp == ".")
{
break;
}
if (strTemp.IndexOf("-ERR") != -1)
{
break;
}
str += strTemp;
}
sw.WriteLine("Quit ");
sw.Flush();
result = str;
return result;
}
Catch ( Exception ex)
{}
return result;
}
thanks in advance ..
Any other protocol you can use? Yes, hotmail/outlook.com now supports IMAP.
But the issue with the code here seems to be that you're creating a new TcpClient every time you run this. If you're running it many times in in a row, Outlook.com/Hotmail will eventually complain. It's as if you've got tons of clients from a single source connecting to their server, which is, when it's not testing code, often a sign of email abuse.
TcpClient tcpclient = new TcpClient(); // Hello, new.
tcpclient.Connect("pop3.live.com", 995);
If you've got a lot to do on the server, keep a single connection active longer, and close it up when you're done.
Every time you run the code in your question, you're creating (and not tcpclient.Close()-ing) a connection to pop3.live.com. I usually only get this error when I've had a lot of connections that don't close properly due to errors when I'm messing with my code.
MSDN actually has a decent example for TcpClient, but you might be more interested in another example from SO here. Check out how it uses using, and nests a loop inside.
using (TcpClient client = new TcpClient())
{
client.Connect("pop3.live.com", 995);
while(variableThatRepresentsRunning)
{
// talk to POP server
}
}
By the way, the best advice I can give here is to tell you not to reinvent the wheel (unless you're just having fun playing with the POP server. Throwing commands via TCP can be lots of fun, especially with IMAP).
OpenPop.NET is a great library to handle POP requests in C#, includes a good MIME parser, and, if you're still working on this, should speed you along quite a bit. Its examples page is excellent.
Go to the mail inbox , you may get mail regarding this and accept it. Otherwise Try to give the request after some time. Because google having some restriction to read mail using pop settings.

Transfer file from Windows Mobile device to...anywhere

I can't seem to find a solution to this issue. I'm trying to get my Compact Framework application on Windows Mobile 6 to have the ability to move a file on its local filesystem to another system.
Here's the solutions I'm aware of:
FTP - Problem with that is most of
the APIs are way to expensive to use.
HTTP PUT - As far as I have been able to find, I can't use anonymous PUT with IIS7, and that's the web server the system is running. (An extreme workaround for this would be to use a different web server to PUT the file, and have that other system transfer it to the IIS system).
Windows share - I would need authentication on the shares, and I haven't seen that a way to pass this authentication through windows mobile.
The last resort would be to require that the devices be cradled to transfer these files, but I'd really like to be able to have these files be transferred wirelessly.
FTP: define "too expensive". Do you mean performance or byte overhead or dollar cost? Here's a free one with source.
HTTP: IIS7 certainly supports hosting web services or custom IHttpHandlers. You could use either for a data upload pretty easily.
A Windows Share simply requires that you to P/Invoke the WNet APIs to map the share, but it's not terribly complex.
I ended up just passing information to a web server via a PHP script.
The options provided above just didn't work out for my situation.
Here's the gist of it. I've got some code in there with progress bars and various checks and handlers unrelated to simply sending a file, but I'm sure you can pick through it. I've removed my authentication code from both the C# and the PHP, but it shouldn't be too hard to roll your own, if necessary.
in C#:
/*
* Here's the short+sweet about how I'm doing this
* 1) Copy the file from mobile device to web server by querying PHP script with paramaters for each line
* 2) PHP script checks 1) If we got the whole data file 2) If this is a duplicate data file
* 3) If it is a duplicate, or we didn't get the whole thing, it goes away. The mobile
* device will hang on to it's data file in the first case (if it's duplicate it deletes it)
* to be tried again later
* 4) The server will then process the data files using a scheduled task/cron job at an appropriate time
*/
private void process_attempts()
{
Uri CheckUrl = new Uri("http://path/to/php/script?action=check");
WebRequest checkReq = WebRequest.Create(CheckUrl);
try
{
WebResponse CheckResp = checkReq.GetResponse();
CheckResp.Close();
}
catch
{
MessageBox.Show("Error! Connection not available. Please make sure you are online.");
this.Invoke(new Close(closeme));
}
StreamReader dataReader = File.OpenText(datafile);
String line = null;
line = dataReader.ReadLine();
while (line != null)
{
Uri Url = new Uri("http://path/to/php/script?action=process&line=" + line);
WebRequest WebReq = WebRequest.Create(Url);
try
{
WebResponse Resp = WebReq.GetResponse();
Resp.Close();
}
catch
{
MessageBox.Show("Error! Connection not available. Please make sure you are online.");
this.Invoke(new Close(closeme));
return;
}
try
{
process_bar.Invoke(new SetInt(SetBarValue), new object[] { processed });
}
catch { }
process_num.Invoke(new SetString(SetNumValue), new object[] { processed + "/" + attempts });
processed++;
line = dataReader.ReadLine();
}
dataReader.Close();
Uri Url2 = new Uri("http://path/to/php/script?action=finalize&lines=" + attempts);
Boolean finalized = false;
WebRequest WebReq2 = WebRequest.Create(Url2);
try
{
WebResponse Resp = WebReq2.GetResponse();
Resp.Close();
finalized = true;
}
catch
{
MessageBox.Show("Error! Connection not available. Please make sure you are online.");
this.Invoke(new Close(closeme));
finalized = false;
}
MessageBox.Show("Done!");
this.Invoke(new Close(closeme));
}
In PHP (thoroughly commented for your benefit!):
<?php
//Get the GET'd values from the C#
//The current line being processed
$line = $_GET['line'];
//Which action we are doing
$action = $_GET['action'];
//# of lines in the source file
$totalLines = $_GET['lines'];
//If we are processing the line, open the data file, and append this new line and a newline.
if($action == "process"){
$dataFile = "tempdata/SOME_KIND_OF_UNIQUE_FILENAME.dat";
//open the file
$fh = fopen($dataFile, 'a');
//Write the line, and a newline to the file
fwrite($fh, $line."\r\n");
//Close the file
fclose($fh);
//Exit the script
exit();
}
//If we are done processing the original file from the C# application, make sure the number of lines in the new file matches that in the
//file we are transferring. An expansion of this could be to compare some kind of hash function value of both files...
if($action == "finalize"){
$dataFile = "tempdata/SOME_KIND_OF_UNIQUE_FILENAME.dat";
//Count the number of lines in the new file
$lines = count(file($dataFile));
//If the new file and the old file have the same number of lines...
if($lines == $totalLines){
//File has the matching number of lines, good enough for me over TCP.
//We should move or rename this file.
}else{
//File does NOT have the same number of lines as the source file.
}
exit();
}
if($action == "check"){
//If a file with this unique file name already exists, delete it.
$dataFile = "tempdata/SOME_KIND_OF_UNIQUE_FILENAME.dat";
if(file_exists($dataFile)){
unlink($dataFile);
}
}
?>

Hostname scanning in C#

Iv'e recently started a new job as an ICT Technician and im creating an Console application which will consists of stuff that will help our daily tools!
My first tool is a Network Scanner, Our system currently runs on Vanilla and Asset tags but the only way we can find the hostname / ip address is by going into the Windows Console tools and nslookup which to me can be improved
I want to create an application in which I enter a 6 digit number and the application will search the whole DNS for a possible match!
Our hostsnames are like so
ICTLN-D006609-edw.srv.internal the d 006609 would be the asset tag for that computer.
I wish to enter that into the Console Application and it search through every hostname and the ones that contain the entered asset tag within the string will be returned along with an ip and full computer name ready for VNC / Remote Desktop.
Firstly how would I go about building this, shall i start the project of as a console app or a WPF. can you provide an example of how I can scan the hostnames via C#, or if there's an opensource C# version can you provide a link.
Any information would be a great help as it will take out alot of issues in the workpalce as we have to ask the customer to go into there My Computer adn properties etc and then read the Computer name back to use which I find pointless.
Regards.
Updates:
*1 C# Version I made: http://pastebin.com/wBWxyyuh
I would actually go about this with PowerShell, since automating tasks is kinda its thing. In fact, here's a PowerShell script to list out all computers visible on the network. This is easily translatable into C# if you really want it there instead.
function Find-Computer( [string]$assetTag ) {
$searcher = New-Object System.DirectoryServices.DirectorySearcher;
$searcher.SearchRoot = New-Object System.DirectoryServices.DirectoryEntry;
$searcher.SearchScope = 'Subtree';
$searcher.PageSize = 1000;
$searcher.Filter = '(objectCategory=computer)';
$results = $searcher.FindAll();
$computers = #();
foreach($result in $results) {
$computers += $result.GetDirectoryEntry();
}
$results.Dispose(); #Explicitly needed to free resources.
$computers |? { $_.Name -match $assetTag }
}
Here's a way you can accomplish this, although it's not the best. You might consider hitting Active Directory to find the legitimate machines on your network. The code below shows how you might resolve a machine name, and shows how to ping it:
static void Main()
{
for (int index = 0; index < 999999; index++)
{
string computerName = string.Format("ICTLN-D{0:000000}-edw.srv.internal", index);
string fqdn = computerName;
try
{
fqdn = Dns.GetHostEntry(computerName).HostName;
}
catch (SocketException exception)
{
Console.WriteLine(">>Computer not found: " + computerName + " - " + exception.Message);
}
using (Ping ping = new Ping())
{
PingReply reply = ping.Send(fqdn);
if (reply.Status == IPStatus.Success)
{
Console.WriteLine(">>Computer is alive: " + computerName);
}
else
{
Console.WriteLine(">>Computer did not respond to ping: " + computerName);
}
}
}
}
Hope that helps...

Categories