Hello everybody and a Happy New Year 2005!
Over the Holiday vacation I created a bunch of test cases for some classes
that I wrote for Tcp/Ip network programming and I found a strange behavior.
If I have a client and a server exchanging messages and if the server
decides to go down for whatever reasons, the client can still send
successfully one message before throwing an exception that tells me the
communication channel is no longer valid. I thought there was something
wrong in my classes but I adapted the two samples from MSDN (Synchronous
Server Socket Example and Synchronous Client Socket Example) to recreate
this behavior.
The Server end accepts the connection from the client and then receives just
one message. After that it shuts down and closes the socket.
The Client connects to the server and then tries to send three messages.
First one is successfully sent and received. The second one is successfully
sent, but obviously not received since the server closed its socket. The
third one fails to be sent and the client throws and exception.
Evidently, my question is why the second message is successfully sent since
the server socket was closed. In the documentation, the Socket.Close method
is said to "close the remote host connection and release all managed and
unmanaged resources associated with the Socket".
I did networking programming in the old VC6.0 days and I don't remember this
being a consistent behavior. I guess it must have to do with the managed
resources that are not garbage-collected very fast, or something.
Did anybody else encountered this thing?
Here is the code for the two ends. If you want to test it, create two C#
console apps and dump the code below in the Class1.cs file for each project.
Any hint will be highly appreciated.
Best regards,
Eddie
////////////////////
// //
// On Server side //
// //
////////////////////
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
public class SynchronousSocketListener
{
public static void StartListening()
{
// Data buffer for incoming data.
byte[] bytes = new Byte[1024];
// Establish the local endpoint for the socket.
// Dns.GetHostName returns the name of the
// host running the application.
IPHostEntry ipHostInfo = Dns.Resolve( Dns.GetHostName() );
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint( ipAddress, 11000 );
// Create a TCP/IP socket.
Socket listener = new Socket( AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp );
// Bind the socket to the local endpoint and
// listen for incoming connections.
try
{
listener.Bind(localEndPoint);
listener.Listen(1);
// Start listening for connections.
Console.WriteLine("Waiting for a connection...");
// Program is suspended while waiting for an incoming connection.
Socket handler = listener.Accept();
string data = null;
// An incoming connection needs to be processed.
bytes = new byte[1024];
int bytesRec = handler.Receive(bytes);
data += Encoding.ASCII.GetString(bytes,0,bytesRec);
// Show the data on the console.
Console.WriteLine( "Text received : {0}", data);
Console.WriteLine( "Shutting down the socket..." );
handler.Shutdown(SocketShutdown.Both);
handler.Close();
Console.WriteLine( "The socket was closed!" );
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
public static int Main(String[] args)
{
StartListening();
Console.WriteLine( "Press <Enter> to Exit..." );
Console.ReadLine();
return 0;
}
}
////////////////////
// //
// On Client side //
// //
////////////////////
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
public class SynchronousSocketClient
{
public static void StartClient()
{
// Data buffer for incoming data.
byte[] bytes = new byte[1024];
// Connect to a remote device.
try
{
// Establish the remote endpoint for the socket.
IPAddress ipAddress = IPAddress.Parse( "10.120.5.107" ); // my IP
address
IPEndPoint remoteEP = new IPEndPoint( ipAddress, 11000 );
// Create a TCP/IP socket.
Socket sender = new Socket( AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp );
// Connect the socket to the remote endpoint. Catch any errors.
try
{
sender.Connect(remoteEP);
Console.WriteLine( "Socket connected to {0}",
sender.RemoteEndPoint.ToString() );
for( int i=1; i<4; i++ )
{
string message = "This is message ";
message += i.ToString();
// Encode the data string into a byte array.
byte[] msg = Encoding.ASCII.GetBytes(message);
// Send the data through the socket.
int bytesSent = sender.Send(msg);
// Show the data on the console.
Console.WriteLine( "Text sent: {0}", message );
// break for 5 seconds
Console.WriteLine( "Sleep five seconds!" );
System.Threading.Thread.Sleep( 5000 );
}
// Release the socket.
sender.Shutdown(SocketShutdown.Both);
sender.Close();
}
catch (ArgumentNullException ane)
{
Console.WriteLine("ArgumentNullException : {0}",ane.ToString());
}
catch (SocketException se)
{
Console.WriteLine("SocketException : {0}",se.ToString());
}
catch (Exception e)
{
Console.WriteLine("Unexpected exception : {0}", e.ToString());
}
}
catch (Exception e)
{
Console.WriteLine( e.ToString());
}
}
public static int Main(String[] args)
{
StartClient();
Console.WriteLine( "Press <Enter> to Exit..." );
Console.ReadLine();
return 0;
}
}
===================================
This list is hosted by DevelopMentor� http://www.develop.com
View archives and manage your subscription(s) at http://discuss.develop.com