Page 1 of 1

Network code with PostgreSQL DB Problem c# resolved

Posted: Tue Apr 25, 2006 4:41 am
by zaneiel
I resolved this issue --
the problem was with the PostgreSQL OLEDB driver
it has a bug that causes it to NOT work within a thread!
the ODBC driver works GREAT! .. i found this info in the PostgreSQL forums so i changed my code over to use the ODBC driver and all is well :)

Just thought u guys should know if anyone is using postgres from a thread and is beating thier heads against thier monitor to no avail... use ODBC.




hey all,
i am pulling my hair out after working on this "threaded network server/client" code.

Anyone know about .net network or thread stuff?

I am new to thread programming so i suspect there are some limitations with thread programming that may not be in normal code? anyway here's what i am doing ..

I have a server that listens to a port .. my client connects to the server and it (the server) spawns a new thread to handle the connection.

I thought this might be a good way to handle clients as you are supposed to be able to handle many clients this way.

ok well any way all that code is working (i will post code in a minute)

so i have this code snippet that connects to my local PostgreSQL database, reads the players_loged_in field (this is just a test field for lack of a beter name) and prints them out to the console, closes the database and datareader and exits.

this code works fine by its self. but when i add a class or a function with the code, i fire it off over the network and it bombs out right after i define the data reader. here's the code, i hope someone can spot my problem as i been to close to the code for to long now to see it i am asuming.

here's the class that works along but not with the code.

using System;
using System.Data;
using System.Data.OleDb;

namespace server
{
public class database
{
public static void GetPlayerPass(string message)
{
string MyConnectString = "Provider=PostgreSQL;USER ID=postgres;PASSWORD=*******;Data Source=127.0.0.1;Extended Properties=;Location=game"; //commented out password
string mySelectQuery = "SELECT name FROM players_loged_in";
OleDbConnection myConnection = new OleDbConnection(MyConnectString);
OleDbCommand myCommand = new OleDbCommand(mySelectQuery, myConnection);
myConnection.Open();
OleDbDataReader myDataReader;
myDataReader = myCommand.ExecuteReader(); // ******* this is where the code bombs ****

while ( myDataReader.Read() )
{
try
{
Console.WriteLine(myDataReader.GetString(0));
}
catch {Console.WriteLine("no data available for your query");}
}

myDataReader.Close();
myConnection.Close();


}
}
}

and here is the rest of the server code that works great by itself by the way :)

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Collections;
using System.Data;
using System.Data.OleDb;
using server;

public class Player
{
public static string[] PlayerList = new string[350];//350 max connections
public static int PlayerListCounter=0;
//ArrayList PlayerList = new ArrayList();
public static void AddPlayer(string name)
{
PlayerList[PlayerListCounter] = name;
PlayerListCounter++;
}

public static void RemovePlayer(string name)
{
ArrayList myal = new ArrayList();
for (int i=0;i<PlayerListCounter;i++)
{myal.Add(PlayerList);} //copy PlayerList over to ArrayList

if (myal.Contains(name))
{
myal.Remove(name);
PlayerListCounter -=1;
for(int i=0;i<PlayerListCounter;i++)
{PlayerList = myal.ToString();}
}
}
}
class ThreadedTcpSrvr
{
private TcpListener client;
public ThreadedTcpSrvr()
{
client = new TcpListener(9050);
client.Start();
Console.WriteLine("Waiting for clients...");
while(true)
{
while (!client.Pending())
{
Thread.Sleep(1000);
}
ConnectionThread newconnection = new ConnectionThread();
newconnection.threadListener = this.client;
Thread newthread = new Thread(new
ThreadStart(newconnection.HandleConnection));
newthread.Start();
}
}//end TcpListener class
public static void Main()
{ database.GetPlayerPass("hello");
ThreadedTcpSrvr server = new ThreadedTcpSrvr();
}
}// ThreadedTcpSrvr

class ConnectionThread
{
public TcpListener threadListener;
private static int connections = 0;

public void HandleConnection()
{
int recv;
byte[] data = new byte[1024];
TcpClient client = threadListener.AcceptTcpClient();
NetworkStream ns = client.GetStream();
connections++;
string message = "Welcome To <need server name>";
Console.WriteLine("New client accepted: {0} active connections", connections);
data = Encoding.ASCII.GetBytes(message);
ns.Write(data, 0, data.Length);
//log player in
//get player ID
//make a player message queue
bool charlogin = true;
bool PlayerAuthUser = false;//user login in
bool PlayerAuthPass = false;//user entering pass
string PlayerName = null;
string PlayerPass = null; //holds player pass
//database PlayerDB = new database();
while(charlogin == true)
{
data = new byte[1024];
recv = ns.Read(data, 0, data.Length);
if (recv == 0)
break;
//Console.WriteLine(Encoding.ASCII.GetString(data));
message = Encoding.ASCII.GetString(data);
//trim the message down to the size of the data so we can parse and print them
message = message.Remove(recv,(1024 - recv));
if (PlayerAuthUser == false)
{ PlayerName = message;
database.GetPlayerPass(message);
PlayerAuthUser = true;
PlayerAuthPass = false;
}
if (PlayerAuthUser == true && PlayerAuthPass == false)
{
if(message == PlayerPass)
{
Player.AddPlayer(PlayerName);//add player to static list
Console.WriteLine("Player: {0} connected to world", PlayerName);
}
}
ns.Write(data, 0, recv);
}
ns.Close();
client.Close();
connections-=1;
Console.WriteLine("Client disconnected: {0} active connections", connections);
}//end HandleConnection
}//end ConnectionThread
//end MyServerClass

i have tried instantiation of the class like database PlayerDB = new database(); and all the other ways i can think of but i think the problem must be something else.

Thanks again for listening to my ramblings guys and i know my code isn't the best as far as "coding standards" so please be kind in your replies :)

Duh, this may help to

Posted: Tue Apr 25, 2006 5:12 am
by zaneiel
here's a clip from my PostgreSQL log file
2006-04-24 21:27:30 LOG: could not receive data from client: No connection could be made because the target machine actively refused it.


2006-04-24 21:27:30 LOG: unexpected EOF on client connection

thanks again for looking at my stuff :)

Wow i found the problem

Posted: Tue Apr 25, 2006 5:58 am
by zaneiel
i seem to have found the problem, although i have no idea why but...

My main function was missing

[STAThread]

this is how it looks now

[STAThread]
public static void Main()
{ Player.GetPlayerPass("hello");
//ThreadedTcpSrvr server = new ThreadedTcpSrvr();
}

so... thanks for the trouble :P at least maybe some of this code will be usefull to someone .. i can post the GUI "temp" client i been using if anyone is interested let me know.

Peace!

somewhat fixed

Posted: Tue Apr 25, 2006 6:59 am
by zaneiel
well i can call my db reading function from Main but not from a spawned thread that handles the connection.

There is definetly somehting not happening when i try to pass variables between threads or try to connect to the db from a new thread.

this whole threads thing is giving me a headache lol
is there a beter network model that can support a couple hundred users without using threads?

or does someone have a "thread safe" method that can help me out?

let me know your thoughts.