Simple TCP Socket Communicator - Please Help

T

Tomasz J

Hello developers,



I am trying to create a simple TCP chat-like communicator.

It will communicate with one peer only sending and receiving messages on the
same port. I guess, this requirement is important. Once the communication is
established it will not receive any other calls, so, I guess, I do not have
to use TcpListener.



I created a TcpClient object. In a infinite a loop running on a separate
thread I try to read incoming data using BinaryReader (cross-thread
communication is handled). Whenever I want to send a message I do it
synchronously on the main thread using the same TcpClient object and
BinaryWriter.



First of all, I am not sure if approach the problem the right way. This is
my first application of that sort.



Second, trying to read incoming data often I receive exceptions like:

A first chance exception of type 'System.IO.EndOfStreamException' occurred
in mscorlib.dll

at System.IO.__Error.EndOfFile()

at System.IO.BinaryReader.FillBuffer(Int32 numBytes)

at System.IO.BinaryReader.ReadUInt32()



Perhaps, I am doing something wrong.



Could anyone advise? Not sure if this is important: I use .Net Framework
3.5.

I will appreciate any hints.



Thomas





The code goes more or less like this:



TcpClient tcpClient = new TcpClient(AddressFamily.InterNetwork);

tcpClient.Connect(someEndPoint);

NetworkStream clientSockStream = tcpClient.GetStream();

BinaryReader reader = new BinaryReader(clientSockStream);

BinaryWriter writer = new BinaryWriter(clientSockStream);



Thread listenerThread;

listenerThread = new Thread(new ThreadStart(ListenToPeer));

listenerThread.Start();



void SendSomeData(int myData) {

writer.Wtite(myData);

}



void ListenToPeer()

{

while(true) {

int data = reader.ReadInt32();

// process data here

}

}
 
S

Steven Cheng [MSFT]

Hi tomasz,

From your description, you're encountering some error when using the
TcpClient to receive data from server, correct?

Since TcpClient work upon a physical Tcp connection, so you should already
have a TcpListener or a TCp socket at another server, correct? Also, based
on my local testing, such problem may due to the adapted Reader or Writer
object that doesn't correctly fit the underlying transfered byte data in
socket buffer. I suggest you directly read the raw byte[] array from the
NetWorkStream (copy it into buffer) and process them further. Also, in
your client reading loop, you can also first use
"NetworkStream.DataAvailable to check whether there is data ready for read
in receive buffer.

here is a simple client app I've used for testing. also, In my read method,
I simply try reading once, you can use a loop in a separate worker thread
to do the same task:

====================================
public partial class Form1 : Form
{
private TcpClient _client;
private StreamReader _reader;
private StreamWriter _writer;
private NetworkStream _stream;
private byte[] buf;

public Form1()
{
InitializeComponent();
}

//create tcp client and connect server
private void button1_Click(object sender, EventArgs e)
{
_client = new TcpClient(AddressFamily.InterNetwork);
_client.Connect("localhost", 8989);

//_client.ConnectIPAddress.Loopback, 8989);
_stream = _client.GetStream();
buf = new byte[_client.ReceiveBufferSize];

_reader = new StreamReader(_stream);
_writer = new StreamWriter(_stream);
}

//read data from buffer if available(and decode it --string data)
private void button2_Click(object sender, EventArgs e)
{
int len;
if (_stream.DataAvailable)
{
len = _stream.Read(buf, 0, buf.Length);
if (len > 0)
textBox1.AppendText("\r\nreceived: " +
Encoding.UTF8.GetString(buf, 0, len));



}


}

//close connection
private void button3_Click(object sender, EventArgs e)
{
_reader.Close();
_writer.Close();
_client.Close();
}
}
================================

Hope this helps.

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
--------------------
 
T

Tomasz J

Thank you for your response.

It seems that testing NetworkStream.DataAvailable before reading any data to
the MemoryStream first and then, deserializing from the MemoryStream using
BinaryReader helps.

But right now I have at least one problem left: writing.
Writing to the NetworkStream using *reused* BinaryWriter occasionally I
receive:

System.IO.IOException - "Unable to write data to the transport connection:
An established connection was aborted by the software in your host machine."

So, according to this message it is my host who, for any reason, aborts the
connection.

What is the best way to write data in such scenario?
Remember that I read data in a loop on one thread but write from the Windows
application on another.
Is this permitted? I do not see any reason why not, since all reads and
writes are always performed on their respective, yet separate threads, but
may be there are threading conflicts between writes and reads? I have no
idea. Should socket reads be synchronized with writes? Or, may be, the
problem is somewhere else.
Please advice. I already spent hours googling for some really good, robust
examples, but found none - only very simplistic demos.

Thanks,

Thomas

Steven Cheng said:
Hi tomasz,

From your description, you're encountering some error when using the
TcpClient to receive data from server, correct?

Since TcpClient work upon a physical Tcp connection, so you should already
have a TcpListener or a TCp socket at another server, correct? Also, based
on my local testing, such problem may due to the adapted Reader or Writer
object that doesn't correctly fit the underlying transfered byte data in
socket buffer. I suggest you directly read the raw byte[] array from the
NetWorkStream (copy it into buffer) and process them further. Also, in
your client reading loop, you can also first use
"NetworkStream.DataAvailable to check whether there is data ready for read
in receive buffer.

here is a simple client app I've used for testing. also, In my read
method,
I simply try reading once, you can use a loop in a separate worker thread
to do the same task:

====================================
public partial class Form1 : Form
{
private TcpClient _client;
private StreamReader _reader;
private StreamWriter _writer;
private NetworkStream _stream;
private byte[] buf;

public Form1()
{
InitializeComponent();
}

//create tcp client and connect server
private void button1_Click(object sender, EventArgs e)
{
_client = new TcpClient(AddressFamily.InterNetwork);
_client.Connect("localhost", 8989);

//_client.ConnectIPAddress.Loopback, 8989);
_stream = _client.GetStream();
buf = new byte[_client.ReceiveBufferSize];

_reader = new StreamReader(_stream);
_writer = new StreamWriter(_stream);
}

//read data from buffer if available(and decode it --string data)
private void button2_Click(object sender, EventArgs e)
{
int len;
if (_stream.DataAvailable)
{
len = _stream.Read(buf, 0, buf.Length);
if (len > 0)
textBox1.AppendText("\r\nreceived: " +
Encoding.UTF8.GetString(buf, 0, len));



}


}

//close connection
private void button3_Click(object sender, EventArgs e)
{
_reader.Close();
_writer.Close();
_client.Close();
}
}
================================

Hope this helps.

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no
rights.
--------------------
From: "Tomasz J" <[email protected]>
Subject: Simple TCP Socket Communicator - Please Help
Date: Thu, 3 Apr 2008 14:06:49 +0200
Hello developers,



I am trying to create a simple TCP chat-like communicator.

It will communicate with one peer only sending and receiving messages on the
same port. I guess, this requirement is important. Once the communication is
established it will not receive any other calls, so, I guess, I do not have
to use TcpListener.



I created a TcpClient object. In a infinite a loop running on a separate
thread I try to read incoming data using BinaryReader (cross-thread
communication is handled). Whenever I want to send a message I do it
synchronously on the main thread using the same TcpClient object and
BinaryWriter.



First of all, I am not sure if approach the problem the right way. This is
my first application of that sort.



Second, trying to read incoming data often I receive exceptions like:

A first chance exception of type 'System.IO.EndOfStreamException' occurred
in mscorlib.dll

at System.IO.__Error.EndOfFile()

at System.IO.BinaryReader.FillBuffer(Int32 numBytes)

at System.IO.BinaryReader.ReadUInt32()



Perhaps, I am doing something wrong.



Could anyone advise? Not sure if this is important: I use .Net Framework
3.5.

I will appreciate any hints.



Thomas





The code goes more or less like this:



TcpClient tcpClient = new TcpClient(AddressFamily.InterNetwork);

tcpClient.Connect(someEndPoint);

NetworkStream clientSockStream = tcpClient.GetStream();

BinaryReader reader = new BinaryReader(clientSockStream);

BinaryWriter writer = new BinaryWriter(clientSockStream);



Thread listenerThread;

listenerThread = new Thread(new ThreadStart(ListenToPeer));

listenerThread.Start();



void SendSomeData(int myData) {

writer.Wtite(myData);

}



void ListenToPeer()

{

while(true) {

int data = reader.ReadInt32();

// process data here

}

}
 
T

Tomasz J

OK, please disregard this message. I found the problem. My connection was
being closed by the remote host for a reason.
Thank you,
Thomas

Tomasz J said:
Thank you for your response.

It seems that testing NetworkStream.DataAvailable before reading any data
to the MemoryStream first and then, deserializing from the MemoryStream
using BinaryReader helps.

But right now I have at least one problem left: writing.
Writing to the NetworkStream using *reused* BinaryWriter occasionally I
receive:

System.IO.IOException - "Unable to write data to the transport connection:
An established connection was aborted by the software in your host
machine."

So, according to this message it is my host who, for any reason, aborts
the connection.

What is the best way to write data in such scenario?
Remember that I read data in a loop on one thread but write from the
Windows application on another.
Is this permitted? I do not see any reason why not, since all reads and
writes are always performed on their respective, yet separate threads, but
may be there are threading conflicts between writes and reads? I have no
idea. Should socket reads be synchronized with writes? Or, may be, the
problem is somewhere else.
Please advice. I already spent hours googling for some really good, robust
examples, but found none - only very simplistic demos.

Thanks,

Thomas

Steven Cheng said:
Hi tomasz,

From your description, you're encountering some error when using the
TcpClient to receive data from server, correct?

Since TcpClient work upon a physical Tcp connection, so you should
already
have a TcpListener or a TCp socket at another server, correct? Also,
based
on my local testing, such problem may due to the adapted Reader or Writer
object that doesn't correctly fit the underlying transfered byte data in
socket buffer. I suggest you directly read the raw byte[] array from the
NetWorkStream (copy it into buffer) and process them further. Also, in
your client reading loop, you can also first use
"NetworkStream.DataAvailable to check whether there is data ready for
read
in receive buffer.

here is a simple client app I've used for testing. also, In my read
method,
I simply try reading once, you can use a loop in a separate worker thread
to do the same task:

====================================
public partial class Form1 : Form
{
private TcpClient _client;
private StreamReader _reader;
private StreamWriter _writer;
private NetworkStream _stream;
private byte[] buf;

public Form1()
{
InitializeComponent();
}

//create tcp client and connect server
private void button1_Click(object sender, EventArgs e)
{
_client = new TcpClient(AddressFamily.InterNetwork);
_client.Connect("localhost", 8989);

//_client.ConnectIPAddress.Loopback, 8989);
_stream = _client.GetStream();
buf = new byte[_client.ReceiveBufferSize];

_reader = new StreamReader(_stream);
_writer = new StreamWriter(_stream);
}

//read data from buffer if available(and decode it --string data)
private void button2_Click(object sender, EventArgs e)
{
int len;
if (_stream.DataAvailable)
{
len = _stream.Read(buf, 0, buf.Length);
if (len > 0)
textBox1.AppendText("\r\nreceived: " +
Encoding.UTF8.GetString(buf, 0, len));



}


}

//close connection
private void button3_Click(object sender, EventArgs e)
{
_reader.Close();
_writer.Close();
_client.Close();
}
}
================================

Hope this helps.

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you.
Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent
issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each
follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no
rights.
--------------------
From: "Tomasz J" <[email protected]>
Subject: Simple TCP Socket Communicator - Please Help
Date: Thu, 3 Apr 2008 14:06:49 +0200
Hello developers,



I am trying to create a simple TCP chat-like communicator.

It will communicate with one peer only sending and receiving messages on the
same port. I guess, this requirement is important. Once the communication is
established it will not receive any other calls, so, I guess, I do not have
to use TcpListener.



I created a TcpClient object. In a infinite a loop running on a separate
thread I try to read incoming data using BinaryReader (cross-thread
communication is handled). Whenever I want to send a message I do it
synchronously on the main thread using the same TcpClient object and
BinaryWriter.



First of all, I am not sure if approach the problem the right way. This
is
my first application of that sort.



Second, trying to read incoming data often I receive exceptions like:

A first chance exception of type 'System.IO.EndOfStreamException'
occurred
in mscorlib.dll

at System.IO.__Error.EndOfFile()

at System.IO.BinaryReader.FillBuffer(Int32 numBytes)

at System.IO.BinaryReader.ReadUInt32()



Perhaps, I am doing something wrong.



Could anyone advise? Not sure if this is important: I use .Net Framework
3.5.

I will appreciate any hints.



Thomas





The code goes more or less like this:



TcpClient tcpClient = new TcpClient(AddressFamily.InterNetwork);

tcpClient.Connect(someEndPoint);

NetworkStream clientSockStream = tcpClient.GetStream();

BinaryReader reader = new BinaryReader(clientSockStream);

BinaryWriter writer = new BinaryWriter(clientSockStream);



Thread listenerThread;

listenerThread = new Thread(new ThreadStart(ListenToPeer));

listenerThread.Start();



void SendSomeData(int myData) {

writer.Wtite(myData);

}



void ListenToPeer()

{

while(true) {

int data = reader.ReadInt32();

// process data here

}

}
 
S

Steven Cheng [MSFT]

Hi Tomasz,

I'm glad that you've figured out the new problem. Just some further
comments to the read/write question you mentioned

Sure, I think it's supported to read/write in separate thread. Actually,
just like what you can do in unmanaged socket application, you can create
different thread to processing data and read/write via the same socket
object. And the data read from socket and write into socket are actually
managed through another underlying buffer(received buffer and send buffer),
data you read from won't affect data you write into wire

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

This posting is provided "AS IS" with no warranties, and confers no rights.

--------------------
From: "Tomasz J" <[email protected]>
Subject: Re: Simple TCP Socket Communicator - Please Help
Date: Fri, 4 Apr 2008 23:52:33 +0200
OK, please disregard this message. I found the problem. My connection was
being closed by the remote host for a reason.
Thank you,
Thomas

Tomasz J said:
Thank you for your response.

It seems that testing NetworkStream.DataAvailable before reading any data
to the MemoryStream first and then, deserializing from the MemoryStream
using BinaryReader helps.

But right now I have at least one problem left: writing.
Writing to the NetworkStream using *reused* BinaryWriter occasionally I
receive:

System.IO.IOException - "Unable to write data to the transport connection:
An established connection was aborted by the software in your host
machine."

So, according to this message it is my host who, for any reason, aborts
the connection.

What is the best way to write data in such scenario?
Remember that I read data in a loop on one thread but write from the
Windows application on another.
Is this permitted? I do not see any reason why not, since all reads and
writes are always performed on their respective, yet separate threads, but
may be there are threading conflicts between writes and reads? I have no
idea. Should socket reads be synchronized with writes? Or, may be, the
problem is somewhere else.
Please advice. I already spent hours googling for some really good, robust
examples, but found none - only very simplistic demos.

Thanks,

Thomas

Steven Cheng said:
Hi tomasz,

From your description, you're encountering some error when using the
TcpClient to receive data from server, correct?

Since TcpClient work upon a physical Tcp connection, so you should
already
have a TcpListener or a TCp socket at another server, correct? Also,
based
on my local testing, such problem may due to the adapted Reader or Writer
object that doesn't correctly fit the underlying transfered byte data in
socket buffer. I suggest you directly read the raw byte[] array from the
NetWorkStream (copy it into buffer) and process them further. Also, in
your client reading loop, you can also first use
"NetworkStream.DataAvailable to check whether there is data ready for
read
in receive buffer.

here is a simple client app I've used for testing. also, In my read
method,
I simply try reading once, you can use a loop in a separate worker thread
to do the same task:

====================================
public partial class Form1 : Form
{
private TcpClient _client;
private StreamReader _reader;
private StreamWriter _writer;
private NetworkStream _stream;
private byte[] buf;

public Form1()
{
InitializeComponent();
}

//create tcp client and connect server
private void button1_Click(object sender, EventArgs e)
{
_client = new TcpClient(AddressFamily.InterNetwork);
_client.Connect("localhost", 8989);

//_client.ConnectIPAddress.Loopback, 8989);
_stream = _client.GetStream();
buf = new byte[_client.ReceiveBufferSize];

_reader = new StreamReader(_stream);
_writer = new StreamWriter(_stream);
}

//read data from buffer if available(and decode it --string data)
private void button2_Click(object sender, EventArgs e)
{
int len;
if (_stream.DataAvailable)
{
len = _stream.Read(buf, 0, buf.Length);
if (len > 0)
textBox1.AppendText("\r\nreceived: " +
Encoding.UTF8.GetString(buf, 0, len));



}


}

//close connection
private void button3_Click(object sender, EventArgs e)
{
_reader.Close();
_writer.Close();
_client.Close();
}
}
================================

Hope this helps.

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you.
Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent
issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each
follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no
rights.
--------------------
From: "Tomasz J" <[email protected]>
Subject: Simple TCP Socket Communicator - Please Help
Date: Thu, 3 Apr 2008 14:06:49 +0200


Hello developers,



I am trying to create a simple TCP chat-like communicator.

It will communicate with one peer only sending and receiving messages on
the
same port. I guess, this requirement is important. Once the communication
is
established it will not receive any other calls, so, I guess, I do not
have
to use TcpListener.



I created a TcpClient object. In a infinite a loop running on a separate
thread I try to read incoming data using BinaryReader (cross-thread
communication is handled). Whenever I want to send a message I do it
synchronously on the main thread using the same TcpClient object and
BinaryWriter.



First of all, I am not sure if approach the problem the right way. This
is
my first application of that sort.



Second, trying to read incoming data often I receive exceptions like:

A first chance exception of type 'System.IO.EndOfStreamException'
occurred
in mscorlib.dll

at System.IO.__Error.EndOfFile()

at System.IO.BinaryReader.FillBuffer(Int32 numBytes)

at System.IO.BinaryReader.ReadUInt32()



Perhaps, I am doing something wrong.



Could anyone advise? Not sure if this is important: I use .Net Framework
3.5.

I will appreciate any hints.



Thomas





The code goes more or less like this:



TcpClient tcpClient = new TcpClient(AddressFamily.InterNetwork);

tcpClient.Connect(someEndPoint);

NetworkStream clientSockStream = tcpClient.GetStream();

BinaryReader reader = new BinaryReader(clientSockStream);

BinaryWriter writer = new BinaryWriter(clientSockStream);



Thread listenerThread;

listenerThread = new Thread(new ThreadStart(ListenToPeer));

listenerThread.Start();



void SendSomeData(int myData) {

writer.Wtite(myData);

}



void ListenToPeer()

{

while(true) {

int data = reader.ReadInt32();

// process data here

}

}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top