got totally confused about the netstream

G

Guest

i am writing a very simple c/s socket program, i just wanted the client to
first write to the server, after server get the message it, write to the
client, the the client write again. here's the codes:

Server:
---------------------------------------------
NetworkStream ns = this.client.GetStream();
StreamReader reader = new StreamReader(ns);
StreamWriter sw = new StreamWriter(ns);

string kidinfo = reader.ReadLine();
sw.Write("a");
sw.Flush();
ns.Flush();
sw.Close();

reader.ReadLine();
---------------------------------------
Client:
--------------------------------------
NetworkStream ns = this.client.GetStream();
StreamReader sr = new StreamReader(ns);
StreamWriter sw = new StreamWriter(ns);
sw.Write(this.interval.ToString());
sw.Flush();
sw.Close();
ns.Flush();

string ps = sr.ReadLine();

sw.Write("ok");
sw.Flush();
sw.Close();
--------------------------------------------------

running them, exceptions came out at the secong "sr.ReadLine()" of the
server and the first "sr.ReadLine()" of the client telling me that "Cannot
access a disposed object.", if i renew the StreamReader as "sr = new
StreamReader(ns)", exception came out telling me "stream is not readable".

it seems that the StreamReader can not work well after the StreamWriter
wrote something.

who can tell me why and how to do this?
thx in advanced
 
G

Guest

Hi,

The basic issue with your code is that you are creating StreamReader and
StreamWriter objects on the same NetworkStream object. So when you close
StreamWriter object or StreamReader object it closes the underlying
NetworkStream object thus making it useless for any further reading or
writing.

So correct this in your code.

Hope this helps.
 
G

Guest

thank you Pasumarthi, but i am still not clear. you say i need two different
NetworkStream to create the StreamReader and StreamWriter respectively, but i
the program there is only one TcpClient, so i can only get one NetworkStream
from the TcpClient.
Is there any way when the server and client need to communicate using both
"StreamReader" and "StreamWriter"? how do people usually deal with it in net
programming?
 
J

Jianwei Sun

I think what he means is that you really shouldn't close it in your code
like this..

sw.Close();
 
G

Guest

Hi fairyvoice,

Jianwei is right. I did not mean that you should create two NetworkStreams
out of your TcpClient. What I meant was that you _should not_ close the
StreamReader or StreamWriter attached to the underlying NetworkStream object.

ALso you need not always create StreamReader and StreamWriter objects to
read/write to a NetworkStream. NetworkStream class itself offer you methods
like Write and Read to send and receive data. Check these methods. Using
these methods you can avoid using StreamReader and StreamWriter classes.

Hope this helps.
 
J

Jon Skeet [C# MVP]

Adityanand Pasumarthi said:
Hi fairyvoice,

Jianwei is right. I did not mean that you should create two NetworkStreams
out of your TcpClient. What I meant was that you _should not_ close the
StreamReader or StreamWriter attached to the underlying NetworkStream object.

ALso you need not always create StreamReader and StreamWriter objects to
read/write to a NetworkStream. NetworkStream class itself offer you methods
like Write and Read to send and receive data. Check these methods. Using
these methods you can avoid using StreamReader and StreamWriter classes.

Well, you can avoid them if you only want to write binary data or if
you want to manually do the transformation between text and binary
data. If you're only writing/reading text, using
StreamReader/StreamWriter is a good way to go.
 
G

Guest

thanks Adityanand and Jianwei. I tried the read and write mathord of the
NetworkStream class and it worked, but i am still a little bored of the
translation between string and bytes. any way, there seems not some perfect
thing in the world
 
G

Guest

Hi fairyvoice,

Check this self contained class below. It may be of some use to you in your
net programming.

struct Message
{
public short sequenceNumeber;
public short length;
public short checksum;
public string data;

public int GetMessageLength()
{
return 2 + 2 + 2 + data.Length;
}

public byte[] ToBytes()
{
byte[] msgBytes = new byte[this.GetMessageLength()];
MemoryStream ms = new MemoryStream(msgBytes);
BinaryWriter bw = new BinaryWriter(ms);
bw.Write(sequenceNumeber);
bw.Write((short)data.Length);
bw.Write(checksum);
bw.Write(Encoding.ASCII.GetBytes(data));
bw.Close();
return msgBytes;
}

public static Message FromBytes(byte[] msgBytes)
{
Message msg = new Message();
MemoryStream ms = new MemoryStream(msgBytes);
BinaryReader br = new BinaryReader(ms);
msg.sequenceNumeber = br.ReadInt16();
msg.length = br.ReadInt16();
msg.checksum = br.ReadInt16();
msg.data = Encoding.ASCII.GetString(br.ReadBytes(msg.length));
br.Close();
return msg;
}
}

The above structure can be used like this...

Message msg = new Message();
msg.sequenceNumeber = 1;
msg.data = "Aditya";
msg.checksum = 90;
msg.length = (short) msg.data.Length;
byte[] msgBytes = msg.ToBytes();
Message msgTemp = Message.FromBytes(msgBytes);
Console.WriteLine(msg.data);

The exact structure may not be useful to you but the approach will give you
some ideas on encapsulating complex data structure to byte conversions for
passing messages between client and server apps.

Hope this helps.
 

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

Similar Threads


Top