Archived

This topic is now archived and is closed to further replies.

Mr Cucumber

C# networking problem

Recommended Posts

I have a problem I have been struggling with for 3 days now. In my application I have some network connection. The client and server sends some data back and forth with no problem at all in the beginning. Both the client and server have a thread to deal with the network stuff. The initialization works fine when the client and server reads passwords and such. Then both the server and client goes into a loop where they wait for a command from the other. These commands never reach their destination. The initialization and the loop is in the same function. I create a NetworkStream from the TcpClient and a StreamReader and StreamWriter from the NetworkStream. These are created directly after the initialization of the connection and are visible in the entire method. In the loop I use a StreamReader.Peek() check to see when a command is available. The Peek method never finds anything to read. In both the server and the client I use the exact same objects that worked without any problems during the initialization in the same methods. Does anyone have any idea why this isnt working? Is there anything I have missed about network streams?

Share this post


Link to post
Share on other sites
I have NO idea what the answer to your problem is, but why don't you just use web-references for sending data between client and server? That is what I have been doing for the last couple of weeks, and it works great!
You won't have to do anything with loops, however all events on the server have to be client-triggered.

Maybe some code?

Edo

quote:

Then both the server and client goes into a loop where they wait for a command from the other.



Eh?


[edited by - edotorpedo on November 15, 2003 4:35:30 PM]

Share this post


Link to post
Share on other sites
So they both wait for commands, but when do you send the commands that are supposed to be received by those loops? before the loop? inside the loop, or in a separate part of the code that's hooked up to the GUI or something?

You could try using BeginReceive and EndReceive stuff. I've found it works quite well for an event-driven networking architecture.

Here's what I do:

I set both sides up with a BeginReceive for 4 bytes (an integer). The idea is to receive the length of data that the other end is going to send.

When the callback fires, I start another BeginReceive based on the integer that I just received. when THAT callback fires, I raise an OnPacket event with the packet stored in a MemoryStream. I then immediately start the header BeginReceive again.

The sender simply has to send a header integer and any data with it (do NOT use MemoryStream.Length, as this is a long!). The receiver doesn't have to poll at all (at least in YOUR code), and gets nice exact-sized packet events.

[edited by - Nypyren on November 15, 2003 8:13:54 PM]

Share this post


Link to post
Share on other sites
Both the server and client waits for commands. But both can when certain conditions are met send commands. I know the code reaches the point where they send the command by having a messagebox shown both before and after the send commands. And I have tried to do so that the client sends a command every time in the loop but no commands can be read.
I have the server and client on the same machine. But that shouldnt be a problem, should it?

This is the code in question for the server (this is obviously not the entire code but this is the code causing the problem):
//Create streams. Both for reading and writing
NetworkStream nst = ((TcpClient)(this.clients[index])).GetStream();
this.nStreams.Add(nst);
StreamReader srt = new StreamReader(((NetworkStream)(((NetworkStream)(this.nStreams[index])))));
this.rStreams.Add(srt);
StreamWriter swt = new StreamWriter(((NetworkStream)(((NetworkStream)(this.nStreams[index])))));
this.wStreams.Add(swt);

//Tell the client that the connection is accepted
((StreamWriter)(this.wStreams[index])).WriteLine("Accepted");
((StreamWriter)(this.wStreams[index])).Flush();

//Read password
string pass = ((StreamReader)(this.rStreams[index])).ReadLine();
// MessageBox.Show("password read: " + pass);

// Thread.Sleep(10000);

//TODO
//The server might have chosen not to use passwords
//This might have been fixed using empty strings

//Check password
if(pass == this.admPassword)
{
((StreamWriter)(this.wStreams[index])).WriteLine("Admin");
((StreamWriter)(this.wStreams[index])).Flush();
}
else if(pass == this.password)
{
((StreamWriter)(this.wStreams[index])).WriteLine("Client");
((StreamWriter)(this.wStreams[index])).Flush();
MessageBox.Show("klietn");
}
else
{
((StreamWriter)(this.wStreams[index])).WriteLine("Wrong");
((StreamWriter)(this.wStreams[index])).Flush();

//Close client
((TcpClient)(this.clients[index])).Close();

//Go to offline mode
this.offline = true;

//Return which kills the thread
return;
}

MessageBox.Show("Klienten tycker: " + ((StreamReader)(this.rStreams[index])).ReadLine());
((StreamWriter)(this.wStreams[index])).WriteLine("Jippie");
((StreamWriter)(this.wStreams[index])).Flush();

Thread.Sleep(5000);
MessageBox.Show("Klienten tycker igen: " + ((StreamReader)(this.rStreams[index])).ReadLine());

// MessageBox.Show("index är i running = " + index);


//A loop that keeps the thread alive as long as the client is connected
for(;
{
//New streams are needed here. Dont know why
// NetworkStream nsl = ((TcpClient)(this.clients[index])).GetStream();
// StreamReader srl = new StreamReader(nsl);
// StreamWriter swl = new StreamWriter(nsl);

//If the user has pressed the update button
//TODO
//Maybe move this to the noderunning method. And when is the update variable reset??
// if(this.update == true)
// {
//// NetworkStream nsl = ((TcpClient)(this.clients[index])).GetStream();
//// StreamWriter swl = new StreamWriter(((NetworkStream)(this.streams[index])));
//
// //Send update command to client
// ((StreamWriter)(this.wStreams[index])).WriteLine("Update");
// ((StreamWriter)(this.wStreams[index])).Flush();
//
// ((StreamWriter)(this.wStreams[index])).Close();
// }



// NetworkStream nsb = ((TcpClient)(this.clients[index])).GetStream();
// StreamReader srb = new StreamReader(((NetworkStream)(this.streams[index])));
// Thread.Sleep(3000);
// MessageBox.Show("Peeken i server = " + ((StreamReader)(this.rStreams[index])).Peek());


//Look for message from client
// if(((StreamReader)(this.rStreams[index])).Peek() >= 0)
// {
//The message
// string mess = ((StreamReader)(this.rStreams[index])).ReadLine();
string mess = ((StreamReader)(this.rStreams[index])).ReadLine();
// ((StreamReader)(this.rStreams[index])).DiscardBufferedData();

MessageBox.Show("Server received message: " + mess);

//The client wishes to update his list of reports
if(mess == "Update")
{
MessageBox.Show("Starting update");
//Receive and send new reports
this.ReceiveNewReports(index);
this.SendNewReports(index);

//The listviews needs to be updated
this.updated = true;
}

//The client wishes to disconnect
else if(mess == "Disconnect")
{
MessageBox.Show("Client disconnected");

//End it
break;
}
// }
}


And this is the code for the client:

//A method to handle the connection part
private void Connect()
{
try
{
//Get the settings for this project
ClientObject co = Project.GetClientObject(this.index);

//Create the tcp client
this.client = new TcpClient();

//Connect to the server
try
{
client.Connect(co.IP, 8005);
}
catch(Exception)
{
MessageBox.Show("Could not establish connection. Entering offline mode", "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);

//Release the wait
lock(this)
{
Monitor.PulseAll(this);

//Enter offline mode
this.offline = true;

return;
}
}
// MessageBox.Show("Connected!");

//Create streams. Both for reading and writing
this.ns = this.client.GetStream();
this.sr = new StreamReader(this.ns);
this.sw = new StreamWriter(this.ns);

//Read the reply from the server
string str = this.sr.ReadLine();
// MessageBox.Show("Received reply from server: " + str);

//Check if connection is accepted
if(str == "Full")
{
MessageBox.Show("Server is full. Try again later. Entering offline mode", "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);

//Release the wait
lock(this)
{
Monitor.PulseAll(this);

//Enter offline mode
this.offline = true;
}
}

//Check if accepted
else if(str == "Accepted")
{
//Send password to server
this.sw.WriteLine(co.Password);
this.sw.Flush();

//Save the reply (which is the password)
string pass = this.sr.ReadLine();
// MessageBox.Show("Server says I'm a: " + pass);

//Check password
if(pass == "Client")
{
lock(this)
{
this.type = NodeType.CLIENT;

this.connected = true;

//Let the program load all bugs
Monitor.PulseAll(this);
}
}

else if(pass == "Admin")
{
lock(this)
{
this.type = NodeType.ADMINISTRATOR;

this.connected = true;

//Let the program load all bugs
Monitor.PulseAll(this);
}
}

else
{
//Kill connections
this.KillAllConnections();

MessageBox.Show("Incorrect password. Check password and try again. Going to offline mode", "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);

//Reset the close field
this.shutdown = false;

//Throw an exception to stop the project
throw(new Exception("PassFail"));
}
}

Thread.Sleep(5000);
this.sw.WriteLine("hejsan hoppsan");
this.sw.Flush();

MessageBox.Show("Servern säger: " + this.sr.ReadLine());

this.sw.WriteLine("Jaså på det viset");
this.sw.Flush();

//Now start the thread running the network service
ThreadStart ts = new ThreadStart(this.NodeRunning);
this.cliThread = new Thread(ts);
this.cliThread.Start();

//Go into a loop that keeps this thread running
for(;
{
//Check if this thread should die
if(this.killConnect == true)
break;

//Whe the user disconnects
if(this.shutdown == true)
{
//Kill connections
this.KillAllConnections();

//Exit loop
break;
}
}

//Reset the close field
this.shutdown = false;
}

catch(Exception e)
{
//Show error message unless the error was incorrect password
if(e.Message != "PassFail")
MessageBox.Show("Network connection failed. Entering offline mode", "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);

MessageBox.Show(e.Message);

//Go to offline mode
this.offline = true;
}
finally
{
lock(this)
{
//No longer connected
this.connected = false;

//Let the program load all bugs
Monitor.PulseAll(this);
}

//Check if the noderunning thread is still running. If so close it
if(this.cliThread.ThreadState != ThreadState.Stopped)
this.cliThread.Abort();
}
}

//A method put in a thread that handles the network connection
public override void NodeRunning()
{
try
{

this.sr.DiscardBufferedData();
//Go into a loop that keeps this thread running
for(;
{
//New streams are needed here. Dont know why
// NetworkStream nsl = this.client.GetStream();
// StreamReader srl = new StreamReader(nsl);
// StreamWriter swl = new StreamWriter(nsl);


// //The client wishes to update his list of reports
// if(this.update == true)
// {
//// NetworkStream nsl = this.client.GetStream();
//// StreamWriter swl = new StreamWriter(this.ns);
//
// //Send update
// this.sw.WriteLine("Update");
// this.sw.Flush();
//// swl.Close();
//
// //Receive and send new reports
// this.SendNewReports(-1);
// this.ReceiveNewReports(-1);
//
// //The listviews needs to be updated
// this.updated = true;
//
// //Update finished
// this.update = false;
// }

// NetworkStream nsb = this.client.GetStream();
// StreamReader srb = new StreamReader(this.ns);

this.sw.WriteLine("BValuba");
this.sw.Flush();


// //Check for message from server
// if(this.ns.DataAvailable == true)
// {
//Get the message
string mess = this.sr.ReadLine();
MessageBox.Show("Client received message: " + mess);
this.sr.DiscardBufferedData();

//Check message
if(mess == "Disconnect")
{
//Show a message about it
MessageBox.Show("Server disconnected. Entering offline mode", "Connection error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

//If the connect thread is till running, kill it
this.killConnect = true;

//Close client
this.client.Close();

//Go to offline mode
this.offline = true;

//Exit loop
break;
}

//The server wishes to update
else if(mess == "Update")
{
this.update = true;
}
// }
}

//When the application has come here it means that the project has been shutdown
}

catch(Exception)
{
//Show error message
MessageBox.Show("Network connection failed. Entering offline mode", "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);

//If the connect thread is till running, kill it
this.killConnect = true;

//Go to offline mode
this.offline = true;
}
finally
{
//No longer connected
this.connected = false;
}
}


[edited by - Mr Cucumber on November 16, 2003 5:43:23 AM]

[edited by - Mr Cucumber on November 16, 2003 5:46:41 AM]

Share this post


Link to post
Share on other sites