NetworkStream problem...
-
I have already asked this question before (but was left unanswered), so I am attempting again, this time refining this question, and hoping that somebody that reads this, would be able to answer. The problem is this... I have this application that sends data to another application on very short intervals (~250ms) between one write and another. This all works great on most PCs but on some others it doesn't work well at all. Reason being, that on the receiving-end, before being able to read all the bytes, the later parts of the data would become all 0s. I don't know if this is a timeout or what? The current code is very simple but works fine (on most PCs):
nsStream.Write(buffer, 0, buffer.Length); // Buffer being a byte[] containing the data
nsStream.Read(buffer, 0, buffer.Length); // Buffer being a byte[] with a pre-determined size
I have attempted to encapsulate the NetworkStream within a BufferedStream but it only made the situation worse - it doesn't work on the PCs that it used to... Any help is greatly appreciated! -
I have already asked this question before (but was left unanswered), so I am attempting again, this time refining this question, and hoping that somebody that reads this, would be able to answer. The problem is this... I have this application that sends data to another application on very short intervals (~250ms) between one write and another. This all works great on most PCs but on some others it doesn't work well at all. Reason being, that on the receiving-end, before being able to read all the bytes, the later parts of the data would become all 0s. I don't know if this is a timeout or what? The current code is very simple but works fine (on most PCs):
nsStream.Write(buffer, 0, buffer.Length); // Buffer being a byte[] containing the data
nsStream.Read(buffer, 0, buffer.Length); // Buffer being a byte[] with a pre-determined size
I have attempted to encapsulate the NetworkStream within a BufferedStream but it only made the situation worse - it doesn't work on the PCs that it used to... Any help is greatly appreciated!So from two lines of code, each running on a different PC, someone should come up with a solution? We would need: - the entire code of the method that writes the data, and its context (which thread, how is it triggered, etc) - the entire code of the method that reads the data, and its context - the declaration and initialization of everything involved in the communication - information on how both PCs are connected - information on the data written each time: is it text? binary data? how much? what does it represent? - at best an example of one data message Your earlier code was terrible: - you abused CanRead and CanWrite properties - you had some kind of throttling with a while loop that could not possibly work reliably. etc. So, I suggest you be very much more specific, and you might get a decent answer. :)
Luc Pattyn [Forum Guidelines] [My Articles]
The quality and detail of your question reflects on the effectiveness of the help you are likely to get. Show formatted code inside PRE tags, and give clear symptoms when describing a problem.
-
So from two lines of code, each running on a different PC, someone should come up with a solution? We would need: - the entire code of the method that writes the data, and its context (which thread, how is it triggered, etc) - the entire code of the method that reads the data, and its context - the declaration and initialization of everything involved in the communication - information on how both PCs are connected - information on the data written each time: is it text? binary data? how much? what does it represent? - at best an example of one data message Your earlier code was terrible: - you abused CanRead and CanWrite properties - you had some kind of throttling with a while loop that could not possibly work reliably. etc. So, I suggest you be very much more specific, and you might get a decent answer. :)
Luc Pattyn [Forum Guidelines] [My Articles]
The quality and detail of your question reflects on the effectiveness of the help you are likely to get. Show formatted code inside PRE tags, and give clear symptoms when describing a problem.
As requested, I will attempt to answer all the questions provided so that I may be provided with an answer which will solve this problem...
Luc Pattyn wrote:
- information on how both PCs are connected
Physically the PCs are on a LAN, thus the network speed should be of no problem. There are multiple connections established in C#, all in TCP/IP. There are about three open ports on each side, each with a separate network stream for separate purposes. However, the exception only occurs in one of these.
Luc Pattyn wrote:
- information on the data written each time: is it text? binary data? how much? what does it represent?
The data transferred in this particular NetworkStream is binary data representing a serialized Bitmap instance. Whilst the length of the serialized Bitmap instance varies every time, it is around ~710500 bytes long...
Luc Pattyn wrote:
- the entire code of the method that writes the data, and its context (which thread, how is it triggered, etc)
The method called is Send(object) which looks as follows:
public bool Send(object oSend)
{
try
{
SendString(Serialize(oSend).Length.ToString());
return SendBytes(Serialize(oSend));
}
catch
{
return false;
}
}Serialize is as follows:
public byte[] Serialize(object oSerialize)
{
if (oSerialize != null)
{
lock (serializeLock)
{
msMem = new MemoryStream();
bf = new BinaryFormatter();try { bf.Serialize(msMem, oSerialize); msMem.Flush(); msMem.Position = 0; oSerialize = null; bf = null; return msMem.ToArray(); } catch { return null; } } } else return null; }
SendString:
public bool SendString(string strSend)
{
try
{
SendBytes(new System.Text.ASCIIEncoding -
As requested, I will attempt to answer all the questions provided so that I may be provided with an answer which will solve this problem...
Luc Pattyn wrote:
- information on how both PCs are connected
Physically the PCs are on a LAN, thus the network speed should be of no problem. There are multiple connections established in C#, all in TCP/IP. There are about three open ports on each side, each with a separate network stream for separate purposes. However, the exception only occurs in one of these.
Luc Pattyn wrote:
- information on the data written each time: is it text? binary data? how much? what does it represent?
The data transferred in this particular NetworkStream is binary data representing a serialized Bitmap instance. Whilst the length of the serialized Bitmap instance varies every time, it is around ~710500 bytes long...
Luc Pattyn wrote:
- the entire code of the method that writes the data, and its context (which thread, how is it triggered, etc)
The method called is Send(object) which looks as follows:
public bool Send(object oSend)
{
try
{
SendString(Serialize(oSend).Length.ToString());
return SendBytes(Serialize(oSend));
}
catch
{
return false;
}
}Serialize is as follows:
public byte[] Serialize(object oSerialize)
{
if (oSerialize != null)
{
lock (serializeLock)
{
msMem = new MemoryStream();
bf = new BinaryFormatter();try { bf.Serialize(msMem, oSerialize); msMem.Flush(); msMem.Position = 0; oSerialize = null; bf = null; return msMem.ToArray(); } catch { return null; } } } else return null; }
SendString:
public bool SendString(string strSend)
{
try
{
SendBytes(new System.Text.ASCIIEncodingHi, if your code works sometimes, that would be a miracle. here are some detailed comments: 1. SendString() your try-catch converts an exception into a bool result, something I don't like since now you MUST check the return value every time you use SendString; as it normally will succeed, why not drop the try-catch and let it throw when there is a problem? 2. SendBytes() 2a. Stream.CanWrite is a constant, either it is always false and your app will fail, or it is always true. Testing it inside a loop doesn't make much sense. 2b. while (nsStream.DataAvailable) {...} is terrible code and the result depends on the speed of your PC, so it is completely unreliable. this loop is wasting CPU cycles; why should a send method be interested in incoming data? and if there is a need, try to get it event-driven or use a separate thread and a Sleep inside the loop. 3. Send() 3a. Calling SendString and NOT checking the result??? 3b. A try-catch that will never catch anything as the methods themselves have their own try-catch? 3c. you send two things (length and data), both in ASCII, without separator. How will the receiver now where the length ends and the data starts? Here is a major problem. What if the first databyte happens to be in the range [0x30,0x39] i.e. an ASCII digit? 3d. NEVER use catch{...} without parameter as it throws away all information about an exception that may be happening; the correct way to do this would be:
try {
....
} catch(AVerySpecificExceptionWeWantToReallyIgnore) {
// empty by design, as this exception is really harmless and does not need logging
} catch(Exception exc) {
log(exc.ToString());
...
}where log(string) is some method to signal a mishap to the user and./or the log file. 4. Serialize() 4a.
oSerialize = null;
does not make sense, as oSerialize is a local variable in a method that is reaching its end. 4b.bf = null;
does not make sense, as bf is a local variable in a method that is reaching its end. 4c. msMem.Flush(); doesn't do a thing. 4d. MemoryStream has a Dispose method, so you should call that when done to clean up things. Hence return msMem.ToArray() should be split in 3 lines. 5. ReceiveBytes() 5a. here you claim the length takes 8 characters; it does not. If you want it that way (good idea!) then make it so, e.g.SendString(Serialize(oSend).Length.ToString("D8"));
in Send(). etc etc a lot of comments on sending also apply to your receiving code. and some overall -
Hi, if your code works sometimes, that would be a miracle. here are some detailed comments: 1. SendString() your try-catch converts an exception into a bool result, something I don't like since now you MUST check the return value every time you use SendString; as it normally will succeed, why not drop the try-catch and let it throw when there is a problem? 2. SendBytes() 2a. Stream.CanWrite is a constant, either it is always false and your app will fail, or it is always true. Testing it inside a loop doesn't make much sense. 2b. while (nsStream.DataAvailable) {...} is terrible code and the result depends on the speed of your PC, so it is completely unreliable. this loop is wasting CPU cycles; why should a send method be interested in incoming data? and if there is a need, try to get it event-driven or use a separate thread and a Sleep inside the loop. 3. Send() 3a. Calling SendString and NOT checking the result??? 3b. A try-catch that will never catch anything as the methods themselves have their own try-catch? 3c. you send two things (length and data), both in ASCII, without separator. How will the receiver now where the length ends and the data starts? Here is a major problem. What if the first databyte happens to be in the range [0x30,0x39] i.e. an ASCII digit? 3d. NEVER use catch{...} without parameter as it throws away all information about an exception that may be happening; the correct way to do this would be:
try {
....
} catch(AVerySpecificExceptionWeWantToReallyIgnore) {
// empty by design, as this exception is really harmless and does not need logging
} catch(Exception exc) {
log(exc.ToString());
...
}where log(string) is some method to signal a mishap to the user and./or the log file. 4. Serialize() 4a.
oSerialize = null;
does not make sense, as oSerialize is a local variable in a method that is reaching its end. 4b.bf = null;
does not make sense, as bf is a local variable in a method that is reaching its end. 4c. msMem.Flush(); doesn't do a thing. 4d. MemoryStream has a Dispose method, so you should call that when done to clean up things. Hence return msMem.ToArray() should be split in 3 lines. 5. ReceiveBytes() 5a. here you claim the length takes 8 characters; it does not. If you want it that way (good idea!) then make it so, e.g.SendString(Serialize(oSend).Length.ToString("D8"));
in Send(). etc etc a lot of comments on sending also apply to your receiving code. and some overallThis is just to inform you that I have just amended most code as you kindly suggested. With regards to exception handling, I must say that I have been a bit careless in implementing them, thus that is why they lack so much - sorry about that. Now I have now implemented two methods: void Send(object obj) - which serializes the object immediately into a NetworkStream. object Receive() - which deserializes from the NetworkStream into an object. Obviously enough this should be much better both in terms of performance and simplicity of code. I'm not sure that this would solve the problem of not being able to receive all the data (I don't expect it too anyway), and I'll keep you informed. I would like to thank you once again, however, if you get an idea on how to ensure that all data is read, I kindly ask you to reply with that :) Thanks so much!
-
This is just to inform you that I have just amended most code as you kindly suggested. With regards to exception handling, I must say that I have been a bit careless in implementing them, thus that is why they lack so much - sorry about that. Now I have now implemented two methods: void Send(object obj) - which serializes the object immediately into a NetworkStream. object Receive() - which deserializes from the NetworkStream into an object. Obviously enough this should be much better both in terms of performance and simplicity of code. I'm not sure that this would solve the problem of not being able to receive all the data (I don't expect it too anyway), and I'll keep you informed. I would like to thank you once again, however, if you get an idea on how to ensure that all data is read, I kindly ask you to reply with that :) Thanks so much!
I expect new code to behave much better, as it improves performance (not needing a byte array) and fixes the length bug (8-digit length being generated now). If there still are problems, describe them accurately, and provide new code if necessary. :)
Luc Pattyn [Forum Guidelines] [My Articles]
The quality and detail of your question reflects on the effectiveness of the help you are likely to get. Show formatted code inside PRE tags, and give clear symptoms when describing a problem.
-
I expect new code to behave much better, as it improves performance (not needing a byte array) and fixes the length bug (8-digit length being generated now). If there still are problems, describe them accurately, and provide new code if necessary. :)
Luc Pattyn [Forum Guidelines] [My Articles]
The quality and detail of your question reflects on the effectiveness of the help you are likely to get. Show formatted code inside PRE tags, and give clear symptoms when describing a problem.
Guess what. It worked! :-D There are still a couple more things to work upon, but that was really starting to bug me! The way I saw it, I thought it had to do with timeouts or something, since the data was partially read, now I realize it's all in that class' miserable coding lol. :-O Thank you so much Luc! You're a life-saver :laugh: :thumbsup::thumbsup: P.S. I wanted to add that post as a Good Answer but it's only appearing on the first post you made... Sorry about that haha.
-
Guess what. It worked! :-D There are still a couple more things to work upon, but that was really starting to bug me! The way I saw it, I thought it had to do with timeouts or something, since the data was partially read, now I realize it's all in that class' miserable coding lol. :-O Thank you so much Luc! You're a life-saver :laugh: :thumbsup::thumbsup: P.S. I wanted to add that post as a Good Answer but it's only appearing on the first post you made... Sorry about that haha.
You're welcome. :)
Luc Pattyn [Forum Guidelines] [My Articles]
The quality and detail of your question reflects on the effectiveness of the help you are likely to get. Show formatted code inside PRE tags, and give clear symptoms when describing a problem.