By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,559 Members | 1,154 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,559 IT Pros & Developers. It's quick & easy.

StreamReader not reading all lines

P: n/a
Hello,

First let me tell you that I'm very new to C# and learning as I go. I'm
trying to write a client application to communicate with a server (that I
didn't write). Each message from the server is on one line (\r\n at end) and
is formed as [Message] [Optional Argument1] [Optional Argument2] - each of
which is seperated by a space. Arguments with spaces in them are enclosed in
quotations.

So, I'm able to open a connection to the server. When I send a message to
it, it immediately responds and I parse that using a streaReader.Readline().
- That part works. The problem is that the server is also sending status
messages every couple of seconds which seem to get lost. I didn't know how
to have it raise an event when data is present at the stream, so I setup a
timer to poll the stream.

I've tried using "streamReader.Peek() != null" but it hangs, I've tried just
streamReader.ReadLine() but it hangs. Any suggestions are greatly
appreciated. I'm using Beta 2

Code is below

Thanks in advance!!
Joe
using System;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.Threading;
using System.Net.Sockets;
using System.IO;

public delegate void ConnectionHandler(bool State);
public delegate void ControlChangeHandler(String Message);

public partial class MMConnection : Form
{

//--------------------------------------------------------------
// Class Variables
private NetworkStream netStream;
private StreamWriter netWriter;
private StreamReader netReader;
public TcpClient netClient;
private bool netClientStart = false;
private bool netClientConnected = false;

private System.Net.IPAddress ipAddress =
System.Net.IPAddress.Parse("127.0.0.1");
private int ipPort = 1632;
private String strUsername = "Contemporary";
private String strPassword = "techspa";
private bool blnLoggedIn = false;

// Define events this class can raise
public event ConnectionHandler OnConnectionChanged;
public event ControlChangeHandler OnControlChanged;

//--------------------------------------------------------------
// Constructor
public MMConnection()
{
InitializeComponent();
}

// Startup the client
public void ConnectionStart()
{
netClientStart = true;
tmrStatus.Enabled = true;
}

public void ConnectionStop ()
{
try
{
logToScreen("Closing connection");

// Close connection
netWriter.Close();
netReader.Close();
netStream.Close();
netClient.Close();
}
catch (Exception e)
{
logToScreen("Error closing connection: " + e.Message.ToString());
}
}

private void StreamWrite (string strMessage)
{
try
{
if (strMessage != "sg") logToScreen("Sending string: " + strMessage);
netWriter.Write(strMessage + "\r\n");
netWriter.Flush();
}
catch (Exception e)
{
netClientConnected = false; // Cannot send - client must have disconnected
Console.WriteLine("Error sending string: " + e.Message.ToString());
}
}

public void MessageSend(string strMessage)
{
StreamWrite(strMessage);
}

// Send Password to the server
private void sendLogin()
{
StreamWrite("li" + " " + strUsername + " " + strPassword);
}

// Parse responses from the server
private void ProcessString(String strData)
{
int foundPosition; //Position of the first space
String firstToken; //The first token (command or error

// Parse out the first token
foundPosition = strData.IndexOf(@" ");
if (foundPosition > -1)
{
firstToken = strData.Substring(0, foundPosition).ToString();
}
else
{
firstToken = strData.ToString();
}

// Act on the first token
switch (firstToken)
{
case "notLoggedIn":
sendLogin();
break;

case "loggedIn":
blnLoggedIn = true;
logToScreen("Logged into MediaMatrix");
UpdateConnectionIndicator(netClient.Connected);
break;

case "statusIs":
blnLoggedIn = true;
break;

case "valueIs":
OnControlChanged(strData);
break;

default: //no token
break;
}
}

private void tmrStatus_Tick(object sender, EventArgs e)
{
if (netClientConnected)
{
tmrRead.Enabled = true;
StreamWrite("sg"); //Status Get
}
else
{
if (netClientStart)
{
try
{

netClient = new TcpClient();
// Create TcpClient and connect to server
netClient.Connect(ipAddress, ipPort);
//UpdateConnectionIndicator(netClient.Connected); //Moved to after
login

// Get network Stream associated with TcpClient
netStream = netClient.GetStream();
netClientConnected = true;
logToScreen("Connection Successfull to: " + ipAddress + " port: " +
ipPort);

// Create readers and writers
netReader = new StreamReader(netStream);
netWriter = new StreamWriter(netStream);
Console.WriteLine("Got Streams!");
}
catch (Exception error)
{
Console.Write ("Error: " + error.ToString());
netClientConnected = false;
}
}
}

// Update the color
//UpdateConnectionIndicator(netClient.Connected);
}

private void logToScreen(String strMessage)
{
lstReceive.Items.Add(strMessage);
Console.WriteLine(strMessage);
}

private void btnSend_Click(object sender, EventArgs e)
{
StreamWrite(txtSend.Text);
}

private void tmrRead_Tick(object sender, EventArgs e)
{
String strData;

try
{
// Read and display lines from the network stream
//while(netStream.DataAvailable)
// logToScreen("End of Stream: " + netReader.EndOfStream);
// logToScreen("Net Reader: " + netReader.ReadLine().ToString());
// logToScreen("End of Stream: " + netReader.EndOfStream);
while (netStream.DataAvailable)
{
try
{
// Grab data from socket
strData = netReader.ReadLine();

// Clean it up a bit
strData = strData.Trim(new char[3] { '\a', '\r', '\n' });

// Send it on to be parsed
logToScreen("Received string: " + strData);
ProcessString(strData);
}
catch (Exception ex)
{
logToScreen("Error reading string: " + ex.Message.ToString());
}
}
}
catch (Exception exc)
{
logToScreen("Error Receiving: " + exc.Message.ToString());
}
}

public static string[] Tokenize(string strIncoming)
{
//TODO: Put regular expresstion
System.Text.RegularExpressions.Regex regFilter = new
System.Text.RegularExpressions.Regex
( @"\a|\s" );

return (regFilter.Split(strIncoming));
}

private void UpdateConnectionIndicator(bool blnConnected)
{
if (blnConnected)
{
staStripConnected.Text = "Connected";
staStripConnected.BackColor = System.Drawing.Color.LightGreen;
}
else
{
staStripConnected.Text = "Not Connected";
staStripConnected.BackColor = System.Drawing.Color.Red;
}

//Raise Event to calling form
OnConnectionChanged(blnConnected);
}

}// MMConnection end
Nov 17 '05 #1
Share this Question
Share on Google+
21 Replies


P: n/a
JoKur,

What I would do is have the StreamReader run in a loop, reading lines as
they come (it will hang in between). The key though is to have the
StreamReader run on another thread, which would raise an event when the
message is received. This way, you won't have to worry about hanging your
application, and can get notifications when the messages come in.

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"JoKur" <Jo*@JoKur.net> wrote in message
news:58**********************************@microsof t.com...
Hello,

First let me tell you that I'm very new to C# and learning as I go. I'm
trying to write a client application to communicate with a server (that I
didn't write). Each message from the server is on one line (\r\n at end)
and
is formed as [Message] [Optional Argument1] [Optional Argument2] - each of
which is seperated by a space. Arguments with spaces in them are enclosed
in
quotations.

So, I'm able to open a connection to the server. When I send a message to
it, it immediately responds and I parse that using a
streaReader.Readline().
- That part works. The problem is that the server is also sending status
messages every couple of seconds which seem to get lost. I didn't know
how
to have it raise an event when data is present at the stream, so I setup a
timer to poll the stream.

I've tried using "streamReader.Peek() != null" but it hangs, I've tried
just
streamReader.ReadLine() but it hangs. Any suggestions are greatly
appreciated. I'm using Beta 2

Code is below

Thanks in advance!!
Joe
using System;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.Threading;
using System.Net.Sockets;
using System.IO;

public delegate void ConnectionHandler(bool State);
public delegate void ControlChangeHandler(String Message);

public partial class MMConnection : Form
{

//--------------------------------------------------------------
// Class Variables
private NetworkStream netStream;
private StreamWriter netWriter;
private StreamReader netReader;
public TcpClient netClient;
private bool netClientStart = false;
private bool netClientConnected = false;

private System.Net.IPAddress ipAddress =
System.Net.IPAddress.Parse("127.0.0.1");
private int ipPort = 1632;
private String strUsername = "Contemporary";
private String strPassword = "techspa";
private bool blnLoggedIn = false;

// Define events this class can raise
public event ConnectionHandler OnConnectionChanged;
public event ControlChangeHandler OnControlChanged;

//--------------------------------------------------------------
// Constructor
public MMConnection()
{
InitializeComponent();
}

// Startup the client
public void ConnectionStart()
{
netClientStart = true;
tmrStatus.Enabled = true;
}

public void ConnectionStop ()
{
try
{
logToScreen("Closing connection");

// Close connection
netWriter.Close();
netReader.Close();
netStream.Close();
netClient.Close();
}
catch (Exception e)
{
logToScreen("Error closing connection: " + e.Message.ToString());
}
}

private void StreamWrite (string strMessage)
{
try
{
if (strMessage != "sg") logToScreen("Sending string: " + strMessage);
netWriter.Write(strMessage + "\r\n");
netWriter.Flush();
}
catch (Exception e)
{
netClientConnected = false; // Cannot send - client must have disconnected
Console.WriteLine("Error sending string: " + e.Message.ToString());
}
}

public void MessageSend(string strMessage)
{
StreamWrite(strMessage);
}

// Send Password to the server
private void sendLogin()
{
StreamWrite("li" + " " + strUsername + " " + strPassword);
}

// Parse responses from the server
private void ProcessString(String strData)
{
int foundPosition; //Position of the first space
String firstToken; //The first token (command or error

// Parse out the first token
foundPosition = strData.IndexOf(@" ");
if (foundPosition > -1)
{
firstToken = strData.Substring(0, foundPosition).ToString();
}
else
{
firstToken = strData.ToString();
}

// Act on the first token
switch (firstToken)
{
case "notLoggedIn":
sendLogin();
break;

case "loggedIn":
blnLoggedIn = true;
logToScreen("Logged into MediaMatrix");
UpdateConnectionIndicator(netClient.Connected);
break;

case "statusIs":
blnLoggedIn = true;
break;

case "valueIs":
OnControlChanged(strData);
break;

default: //no token
break;
}
}

private void tmrStatus_Tick(object sender, EventArgs e)
{
if (netClientConnected)
{
tmrRead.Enabled = true;
StreamWrite("sg"); //Status Get
}
else
{
if (netClientStart)
{
try
{

netClient = new TcpClient();
// Create TcpClient and connect to server
netClient.Connect(ipAddress, ipPort);
//UpdateConnectionIndicator(netClient.Connected); //Moved to after
login

// Get network Stream associated with TcpClient
netStream = netClient.GetStream();
netClientConnected = true;
logToScreen("Connection Successfull to: " + ipAddress + " port: " +
ipPort);

// Create readers and writers
netReader = new StreamReader(netStream);
netWriter = new StreamWriter(netStream);
Console.WriteLine("Got Streams!");
}
catch (Exception error)
{
Console.Write ("Error: " + error.ToString());
netClientConnected = false;
}
}
}

// Update the color
//UpdateConnectionIndicator(netClient.Connected);
}

private void logToScreen(String strMessage)
{
lstReceive.Items.Add(strMessage);
Console.WriteLine(strMessage);
}

private void btnSend_Click(object sender, EventArgs e)
{
StreamWrite(txtSend.Text);
}

private void tmrRead_Tick(object sender, EventArgs e)
{
String strData;

try
{
// Read and display lines from the network stream
//while(netStream.DataAvailable)
// logToScreen("End of Stream: " + netReader.EndOfStream);
// logToScreen("Net Reader: " + netReader.ReadLine().ToString());
// logToScreen("End of Stream: " + netReader.EndOfStream);
while (netStream.DataAvailable)
{
try
{
// Grab data from socket
strData = netReader.ReadLine();

// Clean it up a bit
strData = strData.Trim(new char[3] { '\a', '\r', '\n' });

// Send it on to be parsed
logToScreen("Received string: " + strData);
ProcessString(strData);
}
catch (Exception ex)
{
logToScreen("Error reading string: " + ex.Message.ToString());
}
}
}
catch (Exception exc)
{
logToScreen("Error Receiving: " + exc.Message.ToString());
}
}

public static string[] Tokenize(string strIncoming)
{
//TODO: Put regular expresstion
System.Text.RegularExpressions.Regex regFilter = new
System.Text.RegularExpressions.Regex
( @"\a|\s" );

return (regFilter.Split(strIncoming));
}

private void UpdateConnectionIndicator(bool blnConnected)
{
if (blnConnected)
{
staStripConnected.Text = "Connected";
staStripConnected.BackColor = System.Drawing.Color.LightGreen;
}
else
{
staStripConnected.Text = "Not Connected";
staStripConnected.BackColor = System.Drawing.Color.Red;
}

//Raise Event to calling form
OnConnectionChanged(blnConnected);
}

}// MMConnection end

Nov 17 '05 #2

P: n/a
JoKur <Jo*@JoKur.net> wrote:
First let me tell you that I'm very new to C# and learning as I go. I'm
trying to write a client application to communicate with a server (that I
didn't write). Each message from the server is on one line (\r\n at end) and
is formed as [Message] [Optional Argument1] [Optional Argument2] - each of
which is seperated by a space. Arguments with spaces in them are enclosed in
quotations.

So, I'm able to open a connection to the server. When I send a message to
it, it immediately responds and I parse that using a streaReader.Readline().
- That part works. The problem is that the server is also sending status
messages every couple of seconds which seem to get lost. I didn't know how
to have it raise an event when data is present at the stream, so I setup a
timer to poll the stream.

I've tried using "streamReader.Peek() != null" but it hangs, I've tried just
streamReader.ReadLine() but it hangs. Any suggestions are greatly
appreciated. I'm using Beta 2


Does the server flush the stream after sending the status code? It
sounds like it isn't, or that it's not sending a line terminator after
the status code.

Have you tried using a network sniffer to check that the information is
coming over the wire?

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 17 '05 #3

P: n/a
Jon,

It ends each line with \r\n, which is supposedly what ReadLine() looks for.
I can see this when I connect using Telnet.

I had another thought, is it possible that the server is sending more than
one line but when I'm reading them, I'm only grabbing the first line?

In other words... What happens if I'm accessing the stream (like writing to
it), when something else comes in? Is there a way to ask how many lines it
sees and then do a ReadLine() for each one?

--
Thanks
Joe
"Jon Skeet [C# MVP]" wrote:
JoKur <Jo*@JoKur.net> wrote:
First let me tell you that I'm very new to C# and learning as I go. I'm
trying to write a client application to communicate with a server (that I
didn't write). Each message from the server is on one line (\r\n at end) and
is formed as [Message] [Optional Argument1] [Optional Argument2] - each of
which is seperated by a space. Arguments with spaces in them are enclosed in
quotations.

So, I'm able to open a connection to the server. When I send a message to
it, it immediately responds and I parse that using a streaReader.Readline().
- That part works. The problem is that the server is also sending status
messages every couple of seconds which seem to get lost. I didn't know how
to have it raise an event when data is present at the stream, so I setup a
timer to poll the stream.

I've tried using "streamReader.Peek() != null" but it hangs, I've tried just
streamReader.ReadLine() but it hangs. Any suggestions are greatly
appreciated. I'm using Beta 2


Does the server flush the stream after sending the status code? It
sounds like it isn't, or that it's not sending a line terminator after
the status code.

Have you tried using a network sniffer to check that the information is
coming over the wire?

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too

Nov 17 '05 #4

P: n/a
Nicholas,

Thanks for the suggestion. I had started by trying this approach but
couldn't figure out how to get the polling thread to raise a message to the
running program. Do you have any examples/samples of this?
--
Thanks
Joe
"Nicholas Paldino [.NET/C# MVP]" wrote:
JoKur,

What I would do is have the StreamReader run in a loop, reading lines as
they come (it will hang in between). The key though is to have the
StreamReader run on another thread, which would raise an event when the
message is received. This way, you won't have to worry about hanging your
application, and can get notifications when the messages come in.

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"JoKur" <Jo*@JoKur.net> wrote in message
news:58**********************************@microsof t.com...
Hello,

First let me tell you that I'm very new to C# and learning as I go. I'm
trying to write a client application to communicate with a server (that I
didn't write). Each message from the server is on one line (\r\n at end)
and
is formed as [Message] [Optional Argument1] [Optional Argument2] - each of
which is seperated by a space. Arguments with spaces in them are enclosed
in
quotations.

So, I'm able to open a connection to the server. When I send a message to
it, it immediately responds and I parse that using a
streaReader.Readline().
- That part works. The problem is that the server is also sending status
messages every couple of seconds which seem to get lost. I didn't know
how
to have it raise an event when data is present at the stream, so I setup a
timer to poll the stream.

I've tried using "streamReader.Peek() != null" but it hangs, I've tried
just
streamReader.ReadLine() but it hangs. Any suggestions are greatly
appreciated. I'm using Beta 2

Code is below

Thanks in advance!!
Joe
using System;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.Threading;
using System.Net.Sockets;
using System.IO;

public delegate void ConnectionHandler(bool State);
public delegate void ControlChangeHandler(String Message);

public partial class MMConnection : Form
{

//--------------------------------------------------------------
// Class Variables
private NetworkStream netStream;
private StreamWriter netWriter;
private StreamReader netReader;
public TcpClient netClient;
private bool netClientStart = false;
private bool netClientConnected = false;

private System.Net.IPAddress ipAddress =
System.Net.IPAddress.Parse("127.0.0.1");
private int ipPort = 1632;
private String strUsername = "Contemporary";
private String strPassword = "techspa";
private bool blnLoggedIn = false;

// Define events this class can raise
public event ConnectionHandler OnConnectionChanged;
public event ControlChangeHandler OnControlChanged;

//--------------------------------------------------------------
// Constructor
public MMConnection()
{
InitializeComponent();
}

// Startup the client
public void ConnectionStart()
{
netClientStart = true;
tmrStatus.Enabled = true;
}

public void ConnectionStop ()
{
try
{
logToScreen("Closing connection");

// Close connection
netWriter.Close();
netReader.Close();
netStream.Close();
netClient.Close();
}
catch (Exception e)
{
logToScreen("Error closing connection: " + e.Message.ToString());
}
}

private void StreamWrite (string strMessage)
{
try
{
if (strMessage != "sg") logToScreen("Sending string: " + strMessage);
netWriter.Write(strMessage + "\r\n");
netWriter.Flush();
}
catch (Exception e)
{
netClientConnected = false; // Cannot send - client must have disconnected
Console.WriteLine("Error sending string: " + e.Message.ToString());
}
}

public void MessageSend(string strMessage)
{
StreamWrite(strMessage);
}

// Send Password to the server
private void sendLogin()
{
StreamWrite("li" + " " + strUsername + " " + strPassword);
}

// Parse responses from the server
private void ProcessString(String strData)
{
int foundPosition; //Position of the first space
String firstToken; //The first token (command or error

// Parse out the first token
foundPosition = strData.IndexOf(@" ");
if (foundPosition > -1)
{
firstToken = strData.Substring(0, foundPosition).ToString();
}
else
{
firstToken = strData.ToString();
}

// Act on the first token
switch (firstToken)
{
case "notLoggedIn":
sendLogin();
break;

case "loggedIn":
blnLoggedIn = true;
logToScreen("Logged into MediaMatrix");
UpdateConnectionIndicator(netClient.Connected);
break;

case "statusIs":
blnLoggedIn = true;
break;

case "valueIs":
OnControlChanged(strData);
break;

default: //no token
break;
}
}

private void tmrStatus_Tick(object sender, EventArgs e)
{
if (netClientConnected)
{
tmrRead.Enabled = true;
StreamWrite("sg"); //Status Get
}
else
{
if (netClientStart)
{
try
{

netClient = new TcpClient();
// Create TcpClient and connect to server
netClient.Connect(ipAddress, ipPort);
//UpdateConnectionIndicator(netClient.Connected); //Moved to after
login

// Get network Stream associated with TcpClient
netStream = netClient.GetStream();
netClientConnected = true;
logToScreen("Connection Successfull to: " + ipAddress + " port: " +
ipPort);

// Create readers and writers
netReader = new StreamReader(netStream);
netWriter = new StreamWriter(netStream);
Console.WriteLine("Got Streams!");
}
catch (Exception error)
{
Console.Write ("Error: " + error.ToString());
netClientConnected = false;
}
}
}

// Update the color
//UpdateConnectionIndicator(netClient.Connected);
}

private void logToScreen(String strMessage)
{
lstReceive.Items.Add(strMessage);
Console.WriteLine(strMessage);
}

private void btnSend_Click(object sender, EventArgs e)
{
StreamWrite(txtSend.Text);
}

private void tmrRead_Tick(object sender, EventArgs e)
{
String strData;

try
{
// Read and display lines from the network stream
//while(netStream.DataAvailable)
// logToScreen("End of Stream: " + netReader.EndOfStream);
// logToScreen("Net Reader: " + netReader.ReadLine().ToString());
// logToScreen("End of Stream: " + netReader.EndOfStream);
while (netStream.DataAvailable)
{
try
{
// Grab data from socket
strData = netReader.ReadLine();

// Clean it up a bit
strData = strData.Trim(new char[3] { '\a', '\r', '\n' });

// Send it on to be parsed
logToScreen("Received string: " + strData);
ProcessString(strData);
}
catch (Exception ex)
{
logToScreen("Error reading string: " + ex.Message.ToString());
}
}
}
catch (Exception exc)
{
logToScreen("Error Receiving: " + exc.Message.ToString());
}
}

public static string[] Tokenize(string strIncoming)
{
//TODO: Put regular expresstion
System.Text.RegularExpressions.Regex regFilter = new
System.Text.RegularExpressions.Regex
( @"\a|\s" );

return (regFilter.Split(strIncoming));
}

private void UpdateConnectionIndicator(bool blnConnected)
{
if (blnConnected)
{
staStripConnected.Text = "Connected";
staStripConnected.BackColor = System.Drawing.Color.LightGreen;
}
else
{
staStripConnected.Text = "Not Connected";
staStripConnected.BackColor = System.Drawing.Color.Red;
}

Nov 17 '05 #5

P: n/a
JoKur,

Why not just create an event, and when the call to ReadLine completes,
fire the event. Then, you can attach any listener that you want. You just
have to be careful, because the event will be fired on the thread that is
doing the reading.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"JoKur" <Jo*@JoKur.net> wrote in message
news:78**********************************@microsof t.com...
Nicholas,

Thanks for the suggestion. I had started by trying this approach but
couldn't figure out how to get the polling thread to raise a message to
the
running program. Do you have any examples/samples of this?
--
Thanks
Joe
"Nicholas Paldino [.NET/C# MVP]" wrote:
JoKur,

What I would do is have the StreamReader run in a loop, reading lines
as
they come (it will hang in between). The key though is to have the
StreamReader run on another thread, which would raise an event when the
message is received. This way, you won't have to worry about hanging
your
application, and can get notifications when the messages come in.

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"JoKur" <Jo*@JoKur.net> wrote in message
news:58**********************************@microsof t.com...
> Hello,
>
> First let me tell you that I'm very new to C# and learning as I go.
> I'm
> trying to write a client application to communicate with a server (that
> I
> didn't write). Each message from the server is on one line (\r\n at
> end)
> and
> is formed as [Message] [Optional Argument1] [Optional Argument2] - each
> of
> which is seperated by a space. Arguments with spaces in them are
> enclosed
> in
> quotations.
>
> So, I'm able to open a connection to the server. When I send a message
> to
> it, it immediately responds and I parse that using a
> streaReader.Readline().
> - That part works. The problem is that the server is also sending
> status
> messages every couple of seconds which seem to get lost. I didn't know
> how
> to have it raise an event when data is present at the stream, so I
> setup a
> timer to poll the stream.
>
> I've tried using "streamReader.Peek() != null" but it hangs, I've tried
> just
> streamReader.ReadLine() but it hangs. Any suggestions are greatly
> appreciated. I'm using Beta 2
>
> Code is below
>
> Thanks in advance!!
> Joe
>
>
> using System;
> using System.ComponentModel;
> using System.Data;
> using System.Drawing;
> using System.Text;
> using System.Windows.Forms;
> using System.Collections;
> using System.Threading;
> using System.Net.Sockets;
> using System.IO;
>
> public delegate void ConnectionHandler(bool State);
> public delegate void ControlChangeHandler(String Message);
>
> public partial class MMConnection : Form
> {
>
> //--------------------------------------------------------------
> // Class Variables
> private NetworkStream netStream;
> private StreamWriter netWriter;
> private StreamReader netReader;
> public TcpClient netClient;
> private bool netClientStart = false;
> private bool netClientConnected = false;
>
> private System.Net.IPAddress ipAddress =
> System.Net.IPAddress.Parse("127.0.0.1");
> private int ipPort = 1632;
> private String strUsername = "Contemporary";
> private String strPassword = "techspa";
> private bool blnLoggedIn = false;
>
> // Define events this class can raise
> public event ConnectionHandler OnConnectionChanged;
> public event ControlChangeHandler OnControlChanged;
>
> //--------------------------------------------------------------
> // Constructor
> public MMConnection()
> {
> InitializeComponent();
> }
>
> // Startup the client
> public void ConnectionStart()
> {
> netClientStart = true;
> tmrStatus.Enabled = true;
> }
>
> public void ConnectionStop ()
> {
> try
> {
> logToScreen("Closing connection");
>
> // Close connection
> netWriter.Close();
> netReader.Close();
> netStream.Close();
> netClient.Close();
> }
> catch (Exception e)
> {
> logToScreen("Error closing connection: " + e.Message.ToString());
> }
> }
>
> private void StreamWrite (string strMessage)
> {
> try
> {
> if (strMessage != "sg") logToScreen("Sending string: " + strMessage);
> netWriter.Write(strMessage + "\r\n");
> netWriter.Flush();
> }
> catch (Exception e)
> {
> netClientConnected = false; // Cannot send - client must have
> disconnected
> Console.WriteLine("Error sending string: " + e.Message.ToString());
> }
> }
>
> public void MessageSend(string strMessage)
> {
> StreamWrite(strMessage);
> }
>
> // Send Password to the server
> private void sendLogin()
> {
> StreamWrite("li" + " " + strUsername + " " + strPassword);
> }
>
> // Parse responses from the server
> private void ProcessString(String strData)
> {
> int foundPosition; //Position of the first space
> String firstToken; //The first token (command or error
>
> // Parse out the first token
> foundPosition = strData.IndexOf(@" ");
> if (foundPosition > -1)
> {
> firstToken = strData.Substring(0, foundPosition).ToString();
> }
> else
> {
> firstToken = strData.ToString();
> }
>
> // Act on the first token
> switch (firstToken)
> {
> case "notLoggedIn":
> sendLogin();
> break;
>
> case "loggedIn":
> blnLoggedIn = true;
> logToScreen("Logged into MediaMatrix");
> UpdateConnectionIndicator(netClient.Connected);
> break;
>
> case "statusIs":
> blnLoggedIn = true;
> break;
>
> case "valueIs":
> OnControlChanged(strData);
> break;
>
> default: //no token
> break;
> }
> }
>
> private void tmrStatus_Tick(object sender, EventArgs e)
> {
> if (netClientConnected)
> {
> tmrRead.Enabled = true;
> StreamWrite("sg"); //Status Get
> }
> else
> {
> if (netClientStart)
> {
> try
> {
>
> netClient = new TcpClient();
> // Create TcpClient and connect to server
> netClient.Connect(ipAddress, ipPort);
> //UpdateConnectionIndicator(netClient.Connected); //Moved to after
> login
>
> // Get network Stream associated with TcpClient
> netStream = netClient.GetStream();
> netClientConnected = true;
> logToScreen("Connection Successfull to: " + ipAddress + " port: " +
> ipPort);
>
> // Create readers and writers
> netReader = new StreamReader(netStream);
> netWriter = new StreamWriter(netStream);
> Console.WriteLine("Got Streams!");
> }
> catch (Exception error)
> {
> Console.Write ("Error: " + error.ToString());
> netClientConnected = false;
> }
> }
> }
>
> // Update the color
> //UpdateConnectionIndicator(netClient.Connected);
> }
>
> private void logToScreen(String strMessage)
> {
> lstReceive.Items.Add(strMessage);
> Console.WriteLine(strMessage);
> }
>
> private void btnSend_Click(object sender, EventArgs e)
> {
> StreamWrite(txtSend.Text);
> }
>
> private void tmrRead_Tick(object sender, EventArgs e)
> {
> String strData;
>
> try
> {
> // Read and display lines from the network stream
> //while(netStream.DataAvailable)
> // logToScreen("End of Stream: " + netReader.EndOfStream);
> // logToScreen("Net Reader: " + netReader.ReadLine().ToString());
> // logToScreen("End of Stream: " + netReader.EndOfStream);
> while (netStream.DataAvailable)
> {
> try
> {
> // Grab data from socket
> strData = netReader.ReadLine();
>
> // Clean it up a bit
> strData = strData.Trim(new char[3] { '\a', '\r', '\n' });
>
> // Send it on to be parsed
> logToScreen("Received string: " + strData);
> ProcessString(strData);
> }
> catch (Exception ex)
> {
> logToScreen("Error reading string: " + ex.Message.ToString());
> }
> }
> }
> catch (Exception exc)
> {
> logToScreen("Error Receiving: " + exc.Message.ToString());
> }
> }
>
> public static string[] Tokenize(string strIncoming)
> {
> //TODO: Put regular expresstion
> System.Text.RegularExpressions.Regex regFilter = new
> System.Text.RegularExpressions.Regex
> ( @"\a|\s" );
>
> return (regFilter.Split(strIncoming));
> }
>
> private void UpdateConnectionIndicator(bool blnConnected)
> {
> if (blnConnected)
> {
> staStripConnected.Text = "Connected";
> staStripConnected.BackColor = System.Drawing.Color.LightGreen;
> }
> else
> {
> staStripConnected.Text = "Not Connected";
> staStripConnected.BackColor = System.Drawing.Color.Red;
> }
>

Nov 17 '05 #6

P: n/a
JoKur <Jo*@JoKur.net> wrote:
It ends each line with \r\n, which is supposedly what ReadLine() looks for.
I can see this when I connect using Telnet.

I had another thought, is it possible that the server is sending more than
one line but when I'm reading them, I'm only grabbing the first line?

In other words... What happens if I'm accessing the stream (like writing to
it), when something else comes in? Is there a way to ask how many lines it
sees and then do a ReadLine() for each one?


Just calling ReadLine repeatedly should be fine. It doesn't matter if
you're writing when the line comes in - it will buffer the input.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 17 '05 #7

P: n/a
Being as I'm so new to C#, can you give an example of this?
--
Thanks
Joe
"Nicholas Paldino [.NET/C# MVP]" wrote:
JoKur,

Why not just create an event, and when the call to ReadLine completes,
fire the event. Then, you can attach any listener that you want. You just
have to be careful, because the event will be fired on the thread that is
doing the reading.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"JoKur" <Jo*@JoKur.net> wrote in message
news:78**********************************@microsof t.com...
Nicholas,

Thanks for the suggestion. I had started by trying this approach but
couldn't figure out how to get the polling thread to raise a message to
the
running program. Do you have any examples/samples of this?
--
Thanks
Joe
"Nicholas Paldino [.NET/C# MVP]" wrote:
JoKur,

What I would do is have the StreamReader run in a loop, reading lines
as
they come (it will hang in between). The key though is to have the
StreamReader run on another thread, which would raise an event when the
message is received. This way, you won't have to worry about hanging
your
application, and can get notifications when the messages come in.

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"JoKur" <Jo*@JoKur.net> wrote in message
news:58**********************************@microsof t.com...
> Hello,
>
> First let me tell you that I'm very new to C# and learning as I go.
> I'm
> trying to write a client application to communicate with a server (that
> I
> didn't write). Each message from the server is on one line (\r\n at
> end)
> and
> is formed as [Message] [Optional Argument1] [Optional Argument2] - each
> of
> which is seperated by a space. Arguments with spaces in them are
> enclosed
> in
> quotations.
>
> So, I'm able to open a connection to the server. When I send a message
> to
> it, it immediately responds and I parse that using a
> streaReader.Readline().
> - That part works. The problem is that the server is also sending
> status
> messages every couple of seconds which seem to get lost. I didn't know
> how
> to have it raise an event when data is present at the stream, so I
> setup a
> timer to poll the stream.
>
> I've tried using "streamReader.Peek() != null" but it hangs, I've tried
> just
> streamReader.ReadLine() but it hangs. Any suggestions are greatly
> appreciated. I'm using Beta 2
>
> Code is below
>
> Thanks in advance!!
> Joe
>
>
> using System;
> using System.ComponentModel;
> using System.Data;
> using System.Drawing;
> using System.Text;
> using System.Windows.Forms;
> using System.Collections;
> using System.Threading;
> using System.Net.Sockets;
> using System.IO;
>
> public delegate void ConnectionHandler(bool State);
> public delegate void ControlChangeHandler(String Message);
>
> public partial class MMConnection : Form
> {
>
> //--------------------------------------------------------------
> // Class Variables
> private NetworkStream netStream;
> private StreamWriter netWriter;
> private StreamReader netReader;
> public TcpClient netClient;
> private bool netClientStart = false;
> private bool netClientConnected = false;
>
> private System.Net.IPAddress ipAddress =
> System.Net.IPAddress.Parse("127.0.0.1");
> private int ipPort = 1632;
> private String strUsername = "Contemporary";
> private String strPassword = "techspa";
> private bool blnLoggedIn = false;
>
> // Define events this class can raise
> public event ConnectionHandler OnConnectionChanged;
> public event ControlChangeHandler OnControlChanged;
>
> //--------------------------------------------------------------
> // Constructor
> public MMConnection()
> {
> InitializeComponent();
> }
>
> // Startup the client
> public void ConnectionStart()
> {
> netClientStart = true;
> tmrStatus.Enabled = true;
> }
>
> public void ConnectionStop ()
> {
> try
> {
> logToScreen("Closing connection");
>
> // Close connection
> netWriter.Close();
> netReader.Close();
> netStream.Close();
> netClient.Close();
> }
> catch (Exception e)
> {
> logToScreen("Error closing connection: " + e.Message.ToString());
> }
> }
>
> private void StreamWrite (string strMessage)
> {
> try
> {
> if (strMessage != "sg") logToScreen("Sending string: " + strMessage);
> netWriter.Write(strMessage + "\r\n");
> netWriter.Flush();
> }
> catch (Exception e)
> {
> netClientConnected = false; // Cannot send - client must have
> disconnected
> Console.WriteLine("Error sending string: " + e.Message.ToString());
> }
> }
>
> public void MessageSend(string strMessage)
> {
> StreamWrite(strMessage);
> }
>
> // Send Password to the server
> private void sendLogin()
> {
> StreamWrite("li" + " " + strUsername + " " + strPassword);
> }
>
> // Parse responses from the server
> private void ProcessString(String strData)
> {
> int foundPosition; //Position of the first space
> String firstToken; //The first token (command or error
>
> // Parse out the first token
> foundPosition = strData.IndexOf(@" ");
> if (foundPosition > -1)
> {
> firstToken = strData.Substring(0, foundPosition).ToString();
> }
> else
> {
> firstToken = strData.ToString();
> }
>
> // Act on the first token
> switch (firstToken)
> {
> case "notLoggedIn":
> sendLogin();
> break;
>
> case "loggedIn":
> blnLoggedIn = true;
> logToScreen("Logged into MediaMatrix");
> UpdateConnectionIndicator(netClient.Connected);
> break;
>
> case "statusIs":
> blnLoggedIn = true;
> break;
>
> case "valueIs":
> OnControlChanged(strData);
> break;
>
> default: //no token
> break;
> }
> }
>
> private void tmrStatus_Tick(object sender, EventArgs e)
> {
> if (netClientConnected)
> {
> tmrRead.Enabled = true;
> StreamWrite("sg"); //Status Get
> }
> else
> {
> if (netClientStart)
> {
> try
> {
>
> netClient = new TcpClient();
> // Create TcpClient and connect to server
> netClient.Connect(ipAddress, ipPort);
> //UpdateConnectionIndicator(netClient.Connected); //Moved to after
> login
>
> // Get network Stream associated with TcpClient
> netStream = netClient.GetStream();
> netClientConnected = true;
> logToScreen("Connection Successfull to: " + ipAddress + " port: " +
> ipPort);
>
> // Create readers and writers
> netReader = new StreamReader(netStream);
> netWriter = new StreamWriter(netStream);
> Console.WriteLine("Got Streams!");
> }
> catch (Exception error)
> {
> Console.Write ("Error: " + error.ToString());
> netClientConnected = false;
> }
> }
> }
>
> // Update the color
> //UpdateConnectionIndicator(netClient.Connected);
> }
>
> private void logToScreen(String strMessage)
> {
> lstReceive.Items.Add(strMessage);
> Console.WriteLine(strMessage);
> }
>
> private void btnSend_Click(object sender, EventArgs e)
> {
> StreamWrite(txtSend.Text);
> }
>
> private void tmrRead_Tick(object sender, EventArgs e)
> {
> String strData;
>
> try
> {
> // Read and display lines from the network stream
> //while(netStream.DataAvailable)
> // logToScreen("End of Stream: " + netReader.EndOfStream);
> // logToScreen("Net Reader: " + netReader.ReadLine().ToString());
> // logToScreen("End of Stream: " + netReader.EndOfStream);
> while (netStream.DataAvailable)
> {
> try
> {
> // Grab data from socket
> strData = netReader.ReadLine();
>
> // Clean it up a bit
> strData = strData.Trim(new char[3] { '\a', '\r', '\n' });
>
> // Send it on to be parsed

Nov 17 '05 #8

P: n/a
I thought it should be fine too, but ReadLine() hangs when there's no data
currently in the stream. Any suggestions?
--
Thanks
Joe
"Jon Skeet [C# MVP]" wrote:
JoKur <Jo*@JoKur.net> wrote:
It ends each line with \r\n, which is supposedly what ReadLine() looks for.
I can see this when I connect using Telnet.

I had another thought, is it possible that the server is sending more than
one line but when I'm reading them, I'm only grabbing the first line?

In other words... What happens if I'm accessing the stream (like writing to
it), when something else comes in? Is there a way to ask how many lines it
sees and then do a ReadLine() for each one?


Just calling ReadLine repeatedly should be fine. It doesn't matter if
you're writing when the line comes in - it will buffer the input.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too

Nov 17 '05 #9

P: n/a
JoKur <Jo*@JoKur.net> wrote:
I thought it should be fine too, but ReadLine() hangs when there's no data
currently in the stream. Any suggestions?


It's *meant* to block when there's no data in the stream. I don't see
why that's a problem - if it is, then it sounds like you need to
process the incoming stream in another thread.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 17 '05 #10

P: n/a
Sorry, maybe I'm too much of a newbie to understand what you mean by 'block'.
What happens is the app just freezes (without throwing any exception) when
there is no data. It never resumes, even when new data has been put into the
stream.

The help file on StreamReader.ReadLine() says to do this...

using (StreamReader sr = new StreamReader(path))
{
while (sr.Peek() >= 0)
{
Console.WriteLine(sr.ReadLine());
}
}

When I try to use Peek(), it hang too. Same thing - never resumes, just
freezes right there. So, are the StreamReaders meant to be used with
TCPClient? If not, how should I change my app to make these things work?

If what your saying is true, and these functions are performing as they are
'meant' to, then I'll have to sense when the tread is hung and start a new
thread? Is that right? ...and if I'm starting a new thread everytime one
hangs (which will be about 10 X per second) what happens to the old threads?
(isn't that somewhat like a memory leak?).

Thank you for your time, I'm just so confused!!

--
Thanks
Joe
"Jon Skeet [C# MVP]" wrote:
JoKur <Jo*@JoKur.net> wrote:
I thought it should be fine too, but ReadLine() hangs when there's no data
currently in the stream. Any suggestions?


It's *meant* to block when there's no data in the stream. I don't see
why that's a problem - if it is, then it sounds like you need to
process the incoming stream in another thread.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too

Nov 17 '05 #11

P: n/a
JoKur <Jo*@JoKur.net> wrote:
Sorry, maybe I'm too much of a newbie to understand what you mean by 'block'.
What happens is the app just freezes (without throwing any exception) when
there is no data. It never resumes, even when new data has been put into the
stream.
If a line ending has gone into the stream (and been flushed
appropriately), it should definitely read that.
The help file on StreamReader.ReadLine() says to do this...

using (StreamReader sr = new StreamReader(path))
{
while (sr.Peek() >= 0)
{
Console.WriteLine(sr.ReadLine());
}
}
I'd avoid using Peek myself. Instead, use the fact that ReadLine
returns null when it's finished.
When I try to use Peek(), it hang too. Same thing - never resumes, just
freezes right there. So, are the StreamReaders meant to be used with
TCPClient? If not, how should I change my app to make these things work?
It sounds like the server isn't flushing data or something similar.
If what your saying is true, and these functions are performing as they are
'meant' to, then I'll have to sense when the tread is hung and start a new
thread? Is that right? ...and if I'm starting a new thread everytime one
hangs (which will be about 10 X per second) what happens to the old threads?
(isn't that somewhat like a memory leak?).


You'll be leaking threads - definitely not a good idea. It really
sounds like the server isn't behaving as you expect it to. You should
hook up a network monitor to see what's coming back.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 17 '05 #12

P: n/a
JoKur <Jo*@JoKur.net> wrote:
If what your saying is true, and these functions are performing as they are
'meant' to, then I'll have to sense when the tread is hung and start a new
thread? Is that right? ...and if I'm starting a new thread everytime one
hangs (which will be about 10 X per second) what happens to the old threads?
(isn't that somewhat like a memory leak?).


The problem with your current approach is that, since you call
StreamReader.ReadLine in the main (GUI) thread, the GUI will freeze when
there isn't currently a line to be read (ReadLine halts execution of the
thread on which it was called until there's a line to be read).

One way of solving this problem would be to create a background thread and
call ReadLine in that, over and over until the application has been closed,
notifying the GUI thread of data arrival via events. Then if ReadLine
doesn't return immediately, your GUI will not freeze.

I'd recommend that you read this:
<http://www.pobox.com/~skeet/csharp/threads/>.
Nov 17 '05 #13

P: n/a
Oh hey! I didn't see the link at the bottom of your message... Thanks!
--
Thanks
Joe
"Cool Guy" wrote:
JoKur <Jo*@JoKur.net> wrote:
If what your saying is true, and these functions are performing as they are
'meant' to, then I'll have to sense when the tread is hung and start a new
thread? Is that right? ...and if I'm starting a new thread everytime one
hangs (which will be about 10 X per second) what happens to the old threads?
(isn't that somewhat like a memory leak?).


The problem with your current approach is that, since you call
StreamReader.ReadLine in the main (GUI) thread, the GUI will freeze when
there isn't currently a line to be read (ReadLine halts execution of the
thread on which it was called until there's a line to be read).

One way of solving this problem would be to create a background thread and
call ReadLine in that, over and over until the application has been closed,
notifying the GUI thread of data arrival via events. Then if ReadLine
doesn't return immediately, your GUI will not freeze.

I'd recommend that you read this:
<http://www.pobox.com/~skeet/csharp/threads/>.

Nov 17 '05 #14

P: n/a
Thanks, that's what Nicholas was suggesting also. The problem is I don't
know how to do that. Can you give me an example of creating a thread and
having it raise events? ...or at least point me to some more reading?
--
Thanks
Joe
"Cool Guy" wrote:
JoKur <Jo*@JoKur.net> wrote:
If what your saying is true, and these functions are performing as they are
'meant' to, then I'll have to sense when the tread is hung and start a new
thread? Is that right? ...and if I'm starting a new thread everytime one
hangs (which will be about 10 X per second) what happens to the old threads?
(isn't that somewhat like a memory leak?).


The problem with your current approach is that, since you call
StreamReader.ReadLine in the main (GUI) thread, the GUI will freeze when
there isn't currently a line to be read (ReadLine halts execution of the
thread on which it was called until there's a line to be read).

One way of solving this problem would be to create a background thread and
call ReadLine in that, over and over until the application has been closed,
notifying the GUI thread of data arrival via events. Then if ReadLine
doesn't return immediately, your GUI will not freeze.

I'd recommend that you read this:
<http://www.pobox.com/~skeet/csharp/threads/>.

Nov 17 '05 #15

P: n/a
Thanks for everyone's help. It's closer but still not working. I've done a
lot of reading, testing and rewriting. I verified the problem is not on the
server by writing a test app in VB6 which works fine (win sock raises events
when there's data present).

Below is my latest code. The main app instantiates the SharedBuffer twice,
one for incoming and one for outgoing. That way, the read/write thread can
be completely independant. (The read and write were in seperate threads once
but that actually worked not as well).

Now, I can send a bunch of strings out but the response to each one only
comes back several seconds later (they all come it at once). I'm guessing
that the "DataAvailable" property is the culprit of that. Removing the
DataAvailable check makes it worse though, the readline() hangs for longer
before returning anything. Then, when it returns it has 5-10 lines that it
reads.

At this point, I've been working on this way too long. Please, can somebody
help?? I have a Paypal account and I'm not afraid to use it!

Thanks
Joe
using System;
using System.Collections;
using System.Text;
using System.IO;
using System.Threading;
using System.Net.Sockets;

public class SharedBuffer
{
private ArrayList myBuffer = new ArrayList (1);
private String myName = null;

// constructor
public SharedBuffer()
{
}

public void Add (String strIncoming)
{
// lock this object while setting value in buffers array
lock (this)
{
myBuffer.Insert(0, strIncoming);

// For debugging
Console.WriteLine(myName + ": " + CreateStateOutput());

} // end lock
} // end property Add

public bool DataAvailable
{
get
{
// Return the count of the current array list
if (myBuffer.Count > 0) { return true; }
else { return false; };
} // end accessor set
}

public String Name
{
set
{
myName = value;
} // end accessor set
}

public String Remove ()
{
String strData;

// lock this object while setting value in buffers array
lock (this)
{
if (myBuffer.Count > 0)
{
strData = myBuffer[myBuffer.Count - 1].ToString();

// Delete the last element
myBuffer.RemoveAt(myBuffer.Count - 1);

// For debugging
Console.WriteLine(myName + ": " + CreateStateOutput());
}
else
{
strData = null;
}

} // end lock

return strData;

} // end property Remove


private String CreateStateOutput() // Displays current buffer
{
String strOutput = null; //Holds the output display

// display first line of state information
strOutput = "\r\nBuffer Status... \r\n";

// Show the contents of each buffer
for (int i = 0; i < myBuffer.Count; i++) strOutput += i + ") " +
myBuffer[i] + "\r\n";

return strOutput;
}

} // end class SharedBuffer

public class StreamManager //Poll the stream for new messages
{
// Establish network objects
public TcpClient netClient;
private NetworkStream netStream; // local copy of the network stream
private StreamReader netReader; // local copy of the stream reader
private StreamWriter netWriter;

// Establish network variables
private System.Net.IPAddress ipAddress;
private int ipPort = 1632;
private bool blnStarted; // desired state of the reading thread

private SharedBuffer strBufferReceive; // buffer to put the received
strings into
private SharedBuffer strBufferSend; // buffer to put the received strings
into

// constructor
public StreamManager(System.Net.IPAddress myIP, Int16 myPort, SharedBuffer
myIncomingBuffer, SharedBuffer myOutgoingBuffer)
{
ipAddress = myIP;
ipPort = myPort;
strBufferReceive = myIncomingBuffer;
strBufferSend = myOutgoingBuffer;
}

public void Disconnect()
{
blnStarted = false;
}

// Startup the client
public void Connect()
{
try
{
// Create TcpClient and connect to server
netClient = new TcpClient();
netClient.Connect(ipAddress, ipPort);

// Get network Stream associated with TcpClient
netStream = netClient.GetStream();
blnStarted = true;
Console.WriteLine("Connection Successfull to: " + ipAddress + " port: " +
ipPort);

// Create readers and writers
netReader = new StreamReader(netStream);
netWriter = new StreamWriter(netStream);
Console.WriteLine("Got Streams!");

blnStarted = true;
ReadWrite();
}
catch(Exception ex)
{
Console.WriteLine("Error: " + ex.Message.ToString());
}
}
// Read lines from the stream and raise events returning them
private void ReadWrite()
{
String[] Tokens;
String strData = null;

while (blnStarted)
{
//Do some reading

if (netStream.CanRead && netStream.DataAvailable)
{
try
{
// Grab data from socket
strData = netReader.ReadLine();

// Clean it up a bit
strData = strData.Trim(new char[3] { '\a', '\r', '\n' });
strBufferReceive.Add(strData);
}
catch (Exception ex)
{
Console.WriteLine("Error reading from port or saving to buffer... \r\n
" + ex.Message.ToString());
}
}

//Do some writing
while (strBufferSend.DataAvailable)
{
try
{
// Grab data from buffer and send it
//if (strMessage != "sg") logToScreen("Sending string: " + strMessage);
strData = strBufferSend.Remove();
Console.WriteLine("StreamManager sending string: " + strData);
netWriter.Write(strData + "\r\n");
netWriter.Flush();
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show("Error reading from send buffer or
sending it out port... \r\n" + ex.Message.ToString());
}

} // End write

} // end while started
}

private String[] Tokenize(String strIncoming)
{
String[] strTokens;

strTokens = System.Text.RegularExpressions.Regex.Split(strInco ming,
@"\n|\r");

return strTokens;
}

} // end class StreamManager

Nov 17 '05 #16

P: n/a
JoKur <Jo*@JoKur.net> wrote:
Can you give me an example of creating a thread and
having it raise events?


Following is a small, very simple example of using a worker thread in a
console application. Before you consider using worker threads with forms
(where things aren't so simple), you'll need to be sure that you understand
this example *entirely*.

-----

using System;
using System.Threading;

namespace Threading
{
class EntryPoint
{
[STAThread]
static void Main() {
Worker worker = new Worker();
worker.GotData += new GotDataEventHandler(worker_GotData);
worker.Start();
}

static void worker_GotData(int data) {
Console.WriteLine("Got data: {0}.", data);
}
}

class Worker
{
public void Start() {
// note: no need to keep reference to Thread instance here --
// we don't need it, and the GC won't collect the instance
// until the underlying thread has finished executing
new Thread(new ThreadStart(ThreadJob)).Start();
}

void ThreadJob() {
for (int i = 0; i < 10; ++i) {
// simulate doing some work which blocks execution
Thread.Sleep(500);
// send dummy data back
int dummyData = new Random().Next(1, 101);
if (GotData != null) {
GotData(dummyData);
}
}
}

public event GotDataEventHandler GotData;
}

delegate void GotDataEventHandler(int data);
}

-----

After understanding this example, you'd then really need to read and
understand Jon's article on threading (which I linked to previously) before
you're ready to consider moving onto implementing a multi-threaded GUI
application.
Nov 17 '05 #17

P: n/a
JoKur <Jo*@JoKur.net> wrote:
Removing the
DataAvailable check makes it worse though, the readline() hangs for longer
before returning anything.


If NetworkStream.DataAvailable is true, it doesn't necessarily mean that *a
whole line* is available to be read.

If a whole line is not available to be read, a call to
StreamReader.ReadLine will block until one *is* available.

You really should be doing this in a way that doesn't block the GUI thread.
For example: by calling StreamReader.ReadLine in a *worker thread* instead.
Nov 17 '05 #18

P: n/a
Thanks!
I got the thread running and it works better. But some responses still get
lost. When I'm wriiting to the socket, does it block responses?
--
Thanks
Joe
"Cool Guy" wrote:
JoKur <Jo*@JoKur.net> wrote:
Removing the
DataAvailable check makes it worse though, the readline() hangs for longer
before returning anything.


If NetworkStream.DataAvailable is true, it doesn't necessarily mean that *a
whole line* is available to be read.

If a whole line is not available to be read, a call to
StreamReader.ReadLine will block until one *is* available.

You really should be doing this in a way that doesn't block the GUI thread.
For example: by calling StreamReader.ReadLine in a *worker thread* instead.

Nov 17 '05 #19

P: n/a
JoKur <Jo*@JoKur.net> wrote:
I got the thread running and it works better. But some responses still get
lost.
Just to check: you are logging (via Console.WriteLine, Trace.WriteLine, or
whatever) the result of each call to StreamReader.ReadLine, in order to
determine what you're actually reading -- right?
When I'm wriiting to the socket, does it block responses?


Only if the thread that you're writing in is the same thread as the one
that you're reading in. In this case, the reading would get delayed until
after the writing has completed -- and the writing would get delayed until
after the reading has completed (i.e.: while you're waiting for
StreamReader.ReadLine to complete, you can't write).

If you're reading in one thread and writing in another, neither operation
will block the other.
Nov 17 '05 #20

P: n/a
Well, that may be the problem. Just to clarify, if I'm writing to the stream
at the exact instant the server responds, the streamReader should still
receive the data, but only if the stream reader is in another thread?

--
Thanks
Joe
"Cool Guy" wrote:
JoKur <Jo*@JoKur.net> wrote:
I got the thread running and it works better. But some responses still get
lost.


Just to check: you are logging (via Console.WriteLine, Trace.WriteLine, or
whatever) the result of each call to StreamReader.ReadLine, in order to
determine what you're actually reading -- right?
When I'm wriiting to the socket, does it block responses?


Only if the thread that you're writing in is the same thread as the one
that you're reading in. In this case, the reading would get delayed until
after the writing has completed -- and the writing would get delayed until
after the reading has completed (i.e.: while you're waiting for
StreamReader.ReadLine to complete, you can't write).

If you're reading in one thread and writing in another, neither operation
will block the other.

Nov 17 '05 #21

P: n/a
JoKur <Jo*@JoKur.net> wrote:
Just to clarify, if I'm writing to the stream
at the exact instant the server responds, the streamReader should still
receive the data, but only if the stream reader is in another thread?


(This is designed to be viewed with a fixed-width font.)

Not exactly. The distinction follows.

If, while you're in the process of writing to the NetworkStream, the server
respond --

a. if you're using a single thread for both reading and writing, then
you won't be able to read the response until the write operation has
completed (or has been interrupted); or

b. if you're using one thread for reading and another for
writing, then you won't have to wait for the write operation to
complete (or be interrupted) before you can start reading.
Nov 17 '05 #22

This discussion thread is closed

Replies have been disabled for this discussion.