My SQL Server Can Only Handle 2 players? - sql

I am developing a game using TCP. The clients send and listen the server using TCP. When the server receives a request, then it consults the database (SQL Server Express / Entity Framework) and sends a response back to client.
I'm trying to make a MMORPG, so I need to know all the players locations frequently, so I used a System.Timer to ask the server the location of the players around me.
The problem:
If I configure the timer to trigger for every 500ms a method that asks the server the currently players location, then I can open 2 instances of the client app, but it's laggy. If I configure to trigger for every 50ms, then when I open the second instance, the SQL Server throws this exception often:
"The connection was not closed. The connection's current state is open."
I mean, what the hell? I know I am requesting A LOT of things to the database in a short period, but how do real games deals with this?
Here is one code that throws the error when SQL Server seems to be overloaded (second line of the method):
private List<CharacterDTO> ListAround()
{
List<Character> characters = new List<Character>();
characters = ObjectSet.Character.AsNoTracking().Where(x => x.IsOnline).ToList();
return GetDto(characters);
}

Your real problem is ObjectSet is not Thread Safe. You should be creating a new database context inside ListAround and disposing it when you are done with it, not re-using the same context over and over again.
private List<CharacterDTO> ListAround()
{
List<Character> characters = new List<Character>();
using(var ObjectSet = new TheNameOfYourDataContextType())
{
characters = ObjectSet.Character.AsNoTracking().Where(x => x.IsOnline).ToList();
return GetDto(characters);
}
}

I resolved the problem changing the strategy. Now I don't update the players positions in real time to the database. Instead, I created a list (RAM memory) in the server, so I manage only this list. Eventually I will update the information to the database.

Related

How to put data in gundb at server side as a peer

I thought gun instance in the server was also one of the peers.
But when I put data on the server, the peer can't get the data.
Here is my simple test code.
global.gun.get('servertest').put('yes'); // at server side
gun.get('servertest').once(console.log); // at client side
And it prints undefined.
please, let me know how to use a gun instance on server side.
On the server, run this to actually accept remote connections:
var server = require('http').createServer().listen(8080);
var gun = Gun({web: server});
On the client, run this to connect to your server:
var gun = Gun({peers: ["http://server-ip-or-hostname:8080/gun"]})
As a side note, even if you establish a peer connection to get your data, you still need to handle undefined, as once() might fire several times as data is coming in.
Relevant links:
https://gun.eco/docs/Installation#server:
https://github.com/amark/gun/tree/master/examples
https://github.com/skiqh/gun-cli
EDIT:
To be more explicit about my side note above -- the once callback on your client getting undefined for non-local data is actually by design. It means the client does not have the requested data available yet. It will however request it from its peers, which will try to answer with what they themselves can resolve (locally or from their respective peers). These answers will trigger the callback again (if they got through the CRDT algorithm I think).
Getting undefined on the client could also mean the server's response might have timed out and GUN considered it unanswered. You can prolong the waiting time with .once(callback_function, {wait: time_in_miliseconds}).
As per Hadar's answer, try using on() instead of once() to mitigate race conditions, i.e. your client requesting data from the server before you actually wrote it. Once you got your data and don't want any more updates, you can unsubscribe with gun.get('servertest').off()
Also, it might be noteworthy that GUN instances are not magically linked; having two of them connected does not mean they are one and the same in any way. Conceptually, they are peers in a distributed system, which in GUN's case gives you eventual consistency with all the limits and tradeoffs associated with that.
#skiqh
Hello, Thanks for your answer.
I initiated gun instance well in both server and client.
server
let server = https.createServer(options, app);
server.listen( port );
let gun = Gun({ file: 'data', web: server });
global.gun = gun; // <-- my gun instance on server side
global.gun.get('servertest').put('yes'); <-- I tried to put data
// listening~~~~~
client
window.G = G;
let opt = {};
opt.store = RindexedDB(opt);
opt.localStorage = false;
opt.peers = ['https://my.link/gun'];
G.gun = Gun(opt); // <-- my gun instance on client
gun.get('servertest').once(console.log) // <-- it prints "undefined" even though I put data here by server!
I really want to know how to use methods like .put(), .get(), .on() etc.. on the server side using gun instance.
I tried doing this but failed as I attached the result on my post.
Please, Let me know what Im doing something wrong and the correct way.
Thank you
try gun.on instead of once. on will subscribe to all changes.
your example should work if you run .once only after you write something to the server.
using gun.on on client should work regardless and will trigger the moment the server write somehting

MVC4 Force session update before request ends

We are developing using VS2010 and MVC4, deploying our web app on an IIS 7.5 on Windows7.
Our project has a long running process for which we want to display status and progress.
In order to accomplish this we have a small serializable class with properties that describe the current status. The long operation pseudo code goes like this:
int curentPercentComplete = 0;
EngineStatus status = new EngineStatus();
while (!done) {
status.PercentComplete = curentPercentComplete;
Session['status'] = status;
// do lengthy operation
curentPercentComplete = compute();
done = isJobFinished();
}
We also have an other controller action that tries to retrieve the current status from the session
which then encodes to json and returns it to the browser via an Ajax request.
Our problem is that we always seem to get the last saved data from the previous request, in other words the session object does not seem to update the Session['status'] field during the execution of the while block.
We have tried the session state mode both InProc and StateServer with exactly the same behavior.
Thanks in advance.
It turns out that the MVC framework performs a single update of the session data at the end of the request which means that only the last value is saved.
Since the "lengthy" operation is performed in a single request-response cycle, the idea of storing intermediate status information in the session is plain wrong.

store.load() triggers read + create

I'm developing a app where a list is automatically refreshed every 15 sec. To do so, I load the store every 15 sec from server (sending the params) via php page linked to a postgreSQL DB. So far, so good, and it works OK.
Buy I have noticed that every time the store is loaded, it sends two requests to the server (read + create). While the read request is necessary to load new elements to the store, the create is completely useless, because it sends the whole store as payload and receives nothing making use of the network for nothing.
How can I make the store to read, and only read, from the server when it loads?
Thanks
Some week sago I had some unexpected creates too. Googles learned me that there is an issue with Sencha with store.load(). It seems loaded records stay phantoms after loading. A store.sync() will create all records in a store that are phantoms (means they are not yet in back end).
I have next code in my on load callbacks:
callback: function(records, operation, success) {
var x = records.length;
for (i = 0; i < x; i++) {
records[i].phantom = false;
}
}
This solved my problem.

Current MongoDB server time in VB.Net

How do I get the MongoDB's time or use it in a query from VB.NET?
For example, in the Mongo shell I would do:
db.Cookies.find({ expireOn: { $lt: new Date() } });
In PHP I can easily do something like this:
$model->expireOn = new MongoDate();
How do I approach this in VB.Net? I don't want to use the local machine's time. This obviously doesn't work...
MongoDB.Driver.Builders.Query.LT("expireOn", "new Date()")
If you merely want to remove expired cookies from your collection, you could use the TTL collection feature which will automatically remove expired entries using a background worker on the server, hence using the server's time:
db.Cookies.ensureIndex( { "expireOn": 1 }, { expireAfterSeconds: 0 } )
If you really need to query, use a service program that runs on the server or ensure your clocks are reasonably synchronized because clocks that are considerably off can cause a plethora of problems, especially for web servers and email servers. (Consider HTTP headers like Date, LastModified and If-Modified-Since, Email Timestamps, HMAC/timestamp validation against replay attacks, etc.).

Can Flash be integrated with SQL?

Can Flash be used together with SQL? I have a Flash form and I need to connect it to SQL. If there is any example on the net about this topic. I can't find it.
You don't use ActionScript directly with an SQL database. Instead you make http requests from ActionScript to a server, specifying the correct parameters. A typical opensource setup, is a PHP script communicating with a MySQL DB, but you can use Java with Oracle, Ruby with CouchDB, .NET with SQL or any other possible configuration. The important point is that you must be able to call a server script and pass variables... typically a Restful setup.
Once your PHP script has been properly configured, you can use http POST or http GET to send values from ActionScript.
PHP:
<?php
$updateValue = $_POST["updateValue"];
$dbResult = updateDB( $updateValue ); //This should return the db response
echo( $dbResult );
?>
To call this script from ActionScript, you need to create a variables object.
var variables:URLVariables = new URLVariables();
variables.updateValue = "someResult";
The variable name .updateValue, must match the php variable exactly.
now create a URLRequest Object, specifying the location of your script. For this example the method must be set to POST. You add the variable above to the data setter of the request.
var request:URLRequest = new URLRequest( "yourScript.php" );
request.method = URLRequestMethod.POST;
request.data = variables;
Now create a URLLoader and add an event listener. Do not pass the request created above to the constructor, but to the load method.
var loader:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, onComplete );
loader.load( request );
The handler would look something like this.
private function onComplete( e:Event ) : void
{
trace( URLLoader( e.target ).data.toString() );
}
This example shows how to update and receive a response from a server / db combo. However, you can also query a DB through the script and parse the result. So in the PHP example above, you can output JSON, XML or even a piped string, and this can be consumed by ActionScript.
XML is a popular choice, as ActionScript's e4x support treats XML like a native object.
To treat the response above like an XML response, use the following in the onComplete handler.
private function onComplete( e:Event ) : void
{
var result:XML = XML( URLLoader( e.target ).data );
}
This will throw an error if your xml is poorly formed, so ensure the server script always prints out valid XML, even if there is a DB error.
The problem with this is giving someone a flash file that directly accesses SQL server is very insecure. Even if it's possible, which I have seen SOCKET classes out there to do so for MySQL (though never used it), allowing users to remotely connect to your DB is insecure as the user can sniff the login information.
In my opinion, the best way to do this is to create a Client/Server script. You can easily do this with PHP or ASP.net by using SendAndLoad to send the data you need to pass to SQL via POST fields. You can then send back the values in PHP with:
echo 'success='.+urlencode(data);
With this, flash can access the data via the success field.
I don't personally code flash but I work with a company who develops KIOSK applications for dozens of tradeshow companies, and my job is to store the data, return it to them. This is the method we use. You can make it even cleaner by using actual web services such as SOAP, but this method gets the job done if its just you using it.
You should look into Zend Amf or even the Zend Framework for server side communication with Flash. As far as I know Zend Amf is the fastest way to communicate with PHP ( therefore your database ) also you can pass & return complex Objects from the client to the server and vice versa.
Consider this , for instance. You have a bunch of data in your database , you implement functions in ZF whereas this data is formatted and set as a group of Value Objects. From Flash , you query ZF , Zf queries the database , retrieve & formats your data, return your Value Objects as a JSON string ( for instance ). In Flash, you retrieve you JSON string , decode it and assign your Value Objects to whatever relevant classes you have.
There are plenty of tutorials out there regarding Flash communication with the Zend Framework.
Here's an example:
http://gotoandlearn.com/play.php?id=90