NegotiateStream problem?
I have this code where I would like to authenticate before starting to accept communications from a client. After I add the authentication code, I stop getting the actual data. Here is the code. What is wrong?
using
System;using
System.Net;using
System.Net.Sockets;using
System.Net.Security;using
System.Text;using
System.Threading;namespace
TestApp{
classClass1 {[
STAThread]staticvoid Main(string[] args) {try {ThreadStart threadStart =
new ThreadStart(StartServer);Thread processThread =newThread(threadStart);processThread.Start();
ClientTest();
}
catch (ArgumentNullException e) {Console.WriteLine("ArgumentNullException: {0}", e);}
catch (SocketException e) {Console.WriteLine("SocketException: {0}", e);}
}
privatestaticbool ServerReady =false;privatestatic Int32 port = 11000;privatestaticstring hostName =Dns.GetHostName();privatestaticvoid ClientTest(){
while (!ServerReady)Thread.Sleep(1000);ServerReady =
false;TcpClient client =newTcpClient(hostName, port);client.LingerState =
newLingerOption(true, 0);Byte[] data = System.Text.
Encoding.ASCII.GetBytes("Testing...");NetworkStream stream = client.GetStream();NegotiateStream authStream =newNegotiateStream(stream,true);authStream.AuthenticateAsClient();
if (!authStream.IsAuthenticated)thrownewApplicationException("Failed to authenticate!");authStream.Close();
stream.Write(data, 0, data.Length);
Console.WriteLine("Sent: {0}",Encoding.ASCII.GetString(data));client.Close();
while (!ServerReady)Thread.Sleep(1000);}
privatestaticvoid StartServer(){
IPAddress localAddress;TcpListener Server;localAddress =
Dns.GetHostEntry(hostName).AddressList[0];Server =
newTcpListener(localAddress, port);Server.Start();
ServerReady =
true;TcpClient client = Server.AcceptTcpClient();NetworkStream stream = client.GetStream();NegotiateStream authStream =newNegotiateStream(stream,true);authStream.AuthenticateAsServer();
if (!authStream.IsAuthenticated)thrownewApplicationException("Failed to authenticate!");authStream.Close();
byte[] buffer =newbyte[256];int bytesRead;StringBuilder data =newStringBuilder();while (stream.DataAvailable){
bytesRead = stream.Read(buffer, 0, buffer.Length);
data.Append(
Encoding.ASCII.GetString(buffer, 0, bytesRead));}
Console.WriteLine("Received:" + data.ToString());ServerReady =
true;}
}
}
Thanks.
James
Although you are creating an authStream object, you are doing your read/write operations on the NetworkStream object. You should be reading/writing from the NegotiateStream object, not the NetworkStream object.
This is what you have, Notice that you are calling 'stream.Write' instead of 'authStream.Write'. Also, as Durga mentioned, you shouldn't be closing the authStream object.
NetworkStream stream = client.GetStream();
NegotiateStream authStream = new NegotiateStream(stream, true);
authStream.AuthenticateAsClient();
if (!authStream.IsAuthenticated)
throw new ApplicationException("Failed to authenticate!");
authStream.Close();
stream.Write(data, 0, data.Length);
Thanks, but I still have the same problem.
What I did:
1. Changed the read and write using NegotiateStream object. NegotiateStream does not have a DataAvailable property so I still have to use NetworkStream for that purpose.
2. Removed all closing of the streams.
using
System;using
System.Net;using
System.Net.Sockets;using
System.Net.Security;using
System.Text;using
System.Threading;namespace
TestApp{
class Class1 {[
STAThread]static void Main(string[] args) {try {ThreadStart threadStart =
new ThreadStart(StartServer);Thread processThread = new Thread(threadStart);processThread.Start();
ClientTest();
}
catch (ArgumentNullException e) {Console.WriteLine("ArgumentNullException: {0}", e);}
catch (SocketException e) {Console.WriteLine("SocketException: {0}", e);}
}
private static bool ServerReady = false;private static Int32 port = 11000;private static string hostName = Dns.GetHostName();private static void ClientTest(){
while (!ServerReady)Thread.Sleep(1000);ServerReady =
false;TcpClient client = new TcpClient(hostName, port);client.LingerState =
new LingerOption(true, 0);Byte[] data = System.Text.
Encoding.ASCII.GetBytes("Testing...");NetworkStream stream = client.GetStream();NegotiateStream authStream = new NegotiateStream(stream, true);authStream.AuthenticateAsClient();
if (!authStream.IsAuthenticated)throw new ApplicationException("Failed to authenticate!");authStream.Write(data, 0, data.Length);
Console.WriteLine("Sent: {0}", Encoding.ASCII.GetString(data));client.Close();
while (!ServerReady)Thread.Sleep(1000);}
private static void StartServer(){
IPAddress localAddress;TcpListener Server;localAddress =
Dns.GetHostEntry(hostName).AddressList[0];Server =
new TcpListener(localAddress, port);Server.Start();
ServerReady =
true;TcpClient client = Server.AcceptTcpClient();NetworkStream stream = client.GetStream();NegotiateStream authStream = new NegotiateStream(stream, true);authStream.AuthenticateAsServer();
if (!authStream.IsAuthenticated)throw new ApplicationException("Failed to authenticate!");byte[] buffer = new byte[256];int bytesRead;StringBuilder data = new StringBuilder();while (stream.DataAvailable){
bytesRead = authStream.Read(buffer, 0, buffer.Length);
data.Append(
Encoding.ASCII.GetString(buffer, 0, bytesRead));}
Console.WriteLine("Received:" + data.ToString());ServerReady =
true;}
}
}
The server is exiting even before the data is available.
Look at this fixed version
using
System;
using
System.Net;using
System.Net.Sockets;using
System.Net.Security;using
System.Text;using
System.Threading;namespace
TestApp{
class Class1 {private static bool ServerReady = false;private static Int32 port = 11000;private static string hostName = Dns.GetHostName();static void Main(string[] args) {try {ThreadStart threadStart = new ThreadStart(StartServer);Thread processThread = new Thread(threadStart);processThread.Start();
ClientTest();
}
catch (ArgumentNullException e) {Console.WriteLine("ArgumentNullException: {0}", e);}
catch (SocketException e) {Console.WriteLine("SocketException: {0}", e);}
}
private static void ClientTest(){
while (!ServerReady)Thread.Sleep(1000);ServerReady =
false;TcpClient client =
new TcpClient(hostName, port);// client.LingerState = new LingerOption(true, 0);
Byte[] data = System.Text.Encoding.ASCII.GetBytes("Testing...");NetworkStream stream = client.GetStream();
NegotiateStream authStream =
new NegotiateStream(stream, true);authStream.AuthenticateAsClient();
if (!authStream.IsAuthenticated)throw new ApplicationException("Failed to authenticate!");authStream.Write(data, 0, data.Length);
Console.WriteLine("Sent: {0}", Encoding.ASCII.GetString(data));client.Close();
while (!ServerReady)Thread.Sleep(1000);}
private static void StartServer(){
IPAddress localAddress;
TcpListener Server;
localAddress = Dns.GetHostEntry(hostName).AddressList[0];
Server =
new TcpListener(localAddress, port);Server.Start();
ServerReady =
true;TcpClient client = Server.AcceptTcpClient();
NetworkStream stream = client.GetStream();
NegotiateStream authStream =
new NegotiateStream(stream, true);authStream.AuthenticateAsServer();
if (!authStream.IsAuthenticated)throw new ApplicationException("Failed to authenticate!");byte[] buffer = new byte[256];int bytesRead;StringBuilder data = new StringBuilder();bytesRead = authStream.Read(buffer, 0, buffer.Length);
while (bytesRead > 0){
data.Append(
Encoding.ASCII.GetString(buffer, 0, bytesRead));bytesRead = authStream.Read(buffer, 0, buffer.Length);
}
Console.WriteLine("Received:" + data.ToString());ServerReady =
true;}
}
}
Thanks Durga. That was it.
Issues in my code were:
1. Closed the stream at server end.
2. Did not use NegotiateStream for reading and writing.
3. While loop reading from stream was inaccurate because of use of DataAvailable property of NetworkStream.
Things that did not make difference in resolving the issue:
1. LingerState
2. STAThread attribute
Thanks.
James