ObjectDisposedException on NetworkStream for TCP client (handheld) / server (PC) application

J

jd_ie

Hi all,

I have a client application running on a windows ce .net device, and a
server application running on a PC. I have been experiencing problems
with the tcp connection dropping (ObjectDisposedException for the
NetworkStream) and so I have tried to cut the applications down to
their minimal details, so that I can post them and ask for your opinion
on the problem.

The client sends commands to the server, and the server sends a
response. The tcp connection is opened at the start of the
communication, and is kept open between commands - i.e. a new
connection is not opened each time a command is to be sent.

I have now configured the client, when the button on the main form is
clicked, to send a command (just a longish string) to the server. When
the server receives a command, it sends the response (just another
arbitrary string in this example). I have used a loop on the client
side to send the same command up to 500 times. At about iteration 70, I
get an ObjectDisposedException, and the server reports that the
connection was closed on the client side.

Now an error occurring every 70 times may not seem that often, but in
the real application, I am scanning a barcode, and on the basis of
that, running stored procedures on the server, and the amount of data
going back and forth is more than in this example. I am getting an
error every second scan or so, which is definitely not acceptable ;-) I
am assuming that if I can solve the problem in this example
application, then the (hopefully exact same) problem in my actual
application will also be solved.

The exceptions happen both when the client handheld is connected to the
PC via activesync, and the local lan ip is used to connect to the
server, OR if the client handheld is connected via a wireless lan
access point when NOT connected via activesync. Sometimes an
IOException occurs instead of the ObjectDisposedException. But an
exception occurs without fail, after some iteration of the loop.

The same happens when using the emulator.

An important point is if I make a PC client application, using the same
code as the handheld client application, is successfully sends and
receives the 500 commands and responses, whereas the handheld and
emulator only make it to about 70. The code is below, I'd appreciate
any help, I have no idea why this is happening!

Thanks,

Jonathan



-------------------------------------------------------
SERVER CODE (Visual Studio 2005):
-------------------------------------------------------
Server has a "Server" class which has a child "ClientHandler" class,
one instance of which is created for each incoming TCP connection.

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Collections;
using System.IO;
using System.Windows.Forms;
using System.Data;
using System.Data.SqlClient;

namespace WinPDAServer
{
public class Server : IDisposable
{
private FormMain mainForm;
private Socket socketForClient;
private TcpListener tcpListener;
private static ArrayList clientList = new ArrayList();



public Server(FormMain mainForm)
{
this.mainForm = mainForm;
}



public void Run()
{
tcpListener = new TcpListener(IPAddress.Parse("0.0.0.0"), 6767);
//tcpListener = new
TcpListener(Dns.Resolve("localhost").AddressList[0], 6767);
tcpListener.Start();

mainForm.AddStatus("Server started. Waiting for connection on port
6767.");

// Wait for clients
while (true)
{
// For each client connection, pass the client to a new thread and
// return immediately to listening for the next client
try
{
socketForClient = tcpListener.AcceptSocket();
}
catch (SocketException)
{

}

if (socketForClient.Connected)
{
ClientHandler handler = new ClientHandler(socketForClient,
mainForm);
clientList.Add(handler);

mainForm.AddStatus("");
mainForm.AddStatus("Client connected");
handler.StartRead();
}
}
}



/// <summary>
/// Clean up before object is destroyed
/// </summary>
public void Dispose()
{
if (socketForClient != null)
{
socketForClient.Close();
}

if (tcpListener != null)
{
tcpListener.Stop();
}
}



/// <summary>
/// Nested ClientHandler class. Each instance handles one client
/// </summary>
public class ClientHandler : IDisposable
{
private const int BufferSize = 1024;
private byte[] buffer;
private Socket socket;
private NetworkStream networkStream;
private AsyncCallback readCommandCallback;
private FormMain mainForm;

private string dateTimeConnected;
private string dateConnected;
private string strRead;


public ClientHandler(Socket socketForClient, FormMain mainForm)
{
this.mainForm = mainForm;
this.socket = socketForClient;
networkStream = new NetworkStream(socketForClient);
buffer = new byte[BufferSize];

// Set callbacks
readCommandCallback = new
AsyncCallback(this.OnReadCommandComplete);

dateTimeConnected = DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss");
dateConnected = DateTime.Now.ToString("yyyy-MM-dd");
}



public void StartRead()
{
strRead = "";
networkStream.BeginRead(buffer, 0, buffer.Length,
readCommandCallback, null);
}



private void OnReadCommandComplete(IAsyncResult ar)
{
int bytesRead = 0;

try
{
bytesRead = networkStream.EndRead(ar);
}
catch (Exception)
{
mainForm.AddStatus("Client disconnected");
mainForm.AddStatus("");
networkStream.Close();
socket.Close();
clientList.Remove(this);
}

if (bytesRead > 0)
{
strRead += Encoding.ASCII.GetString(buffer, 0, bytesRead);

if (strRead.IndexOf("\0") != -1)
{
// Have read entire string, so save it and read the file contents
string strCommandString = strRead.Substring(0, strRead.Length -
1);
mainForm.AddStatus("Received command: " + strCommandString +
"...");

string strResponse = "This is a test command response:
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz\0";
networkStream.Write(ASCIIEncoding.ASCII.GetBytes(strResponse), 0,
strResponse.Length);

// Response has been sent, so wait for next
command
strRead = "";
networkStream.BeginRead(buffer, 0,
buffer.Length, readCommandCallback, null);
}
else
{
// Have not read whole string, so read rest of it
networkStream.BeginRead(buffer, 0, buffer.Length,
readCommandCallback, null);
return;
}
}
else
{
mainForm.AddStatus("Client disconnected");
mainForm.AddStatus("");
networkStream.Close();
socket.Close();
clientList.Remove(this);
}
}



/// <summary>
/// Release resources before object is destroyed
/// </summary>
public void Dispose()
{
if (networkStream != null) networkStream.Close();
if (socket != null) socket.Close();
networkStream = null;
socket = null;

// Remove client from array list
clientList.Remove(this);
}

}

}
}


------------------------------------------
HANDHELD CLIENT CODE:
-----------------------------------------

private void cmdSendData_Click(object sender, System.EventArgs e)
{
// Connect to server
ApplicationStream = EstablishConnection();

for (int j = 0; j < 500; j++)
{
// Send command
byte[] bytesToSend = new byte[256];
bytesToSend = ASCIIEncoding.ASCII.GetBytes("This a test command:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
ccccccccccccccccccccccccccccccccccccccccccccccc
ddddddddddddddddddddddddddddddddddddddddddd
eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\0");
try
{
ApplicationStream.Write(bytesToSend, 0, bytesToSend.Length);
}
catch (ObjectDisposedException)
{
MessageBox.Show("ObjectDisposedException occurred writing to
stream");
return;
}
catch (Exception)
{
MessageBox.Show("Exception occurred writing to stream");
return;
}

// Get result
string strResult = "";
bool bReceivedResponse = false;
int iBufferLength = 8096;
byte[] buffer = new byte[iBufferLength];
int numBytesRead = 0;
do
{
for (int i = 0; i < iBufferLength; i++)
{
buffer = Convert.ToByte(' ');
}
try
{
numBytesRead = ApplicationStream.Read(buffer, 0, iBufferLength);
}
catch (IOException)
{
MessageBox.Show("IOException occurred reading from stream");
return;
}
catch (ObjectDisposedException)
{
MessageBox.Show("ObjectDisposedException occurred reading from
stream");
return;
}

if (numBytesRead > 0)
{
// Convert and add to input string
strResult += ASCIIEncoding.ASCII.GetString(buffer, 0,
numBytesRead);


if (strResult.IndexOf("\0") != -1)
{
// Finished reading response successfully
strResult = strResult.Substring(0, strResult.Length - 1);
bReceivedResponse = true;
break;
}
}
}
while (numBytesRead > 0);

Cursor.Current = Cursors.Default;
if (bReceivedResponse)
{
lblReceivedData.Text = strResult;
}
else
{
lblReceivedData.Text = "No data";
}
}
}

public NetworkStream EstablishConnection()
{
TcpClient client = new TcpClient();
IPEndPoint ipendpoint = new
IPEndPoint(IPAddress.Parse(Utilities.GetAppSetting("ServerIPAddress")),
GlobalData.SERVER_PORT);

try
{
client.Connect(ipendpoint);
}
catch (Exception)
{
// Connection failed
client.Close();
return null;
}

// Connection successful
return client.GetStream();
}
 
B

Bipin_Expert

Hi,
There are 2 things which you also know that handheld devices have
lesser processing capacity and memory as compared to desktop pc's thats
why you are able to send and receive 500 commands and response on
desktop whereas only 70 on device.
Also you can try using threading for a delay in sending commands rather
than sending them in a loop, or your client app should wait for
response after sending a command, and next command should be issued
once response is received.

Regards,
Bipin Kesharwani
(Developer)

Palewar Techno Solutions
Pocket PC & Mobile Software Development
Nagpur, India

http://www.palewar.com
 
J

jonathan.dudley

Hi Binip,

Thanks for the reply. But is it not true that I am waiting for the
response from the server before sending the next command? I will try to
put in a small time delay between each sending operation, and see if
that stops the connection from dropping.

Regards,

Jonathan
 
J

jonathan.dudley

Hi again Bipin,

I put in a line to pause execution

System.Threading.Thread.Sleep(1000);

at the end of the for loop - thus after each response is received. I
have put in delays of 100ms, 500ms and 1 second, and for all three
delays, it is on iteration 64 of the loop that the exception occurs.
This seems a little strange.

Any ideas? I can send you the application if you would like to run
it...

Jonathan
 

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