server client data send problem

Hi.
I am able to successfully connect the client and server together using the Sockets/tcpclient/tcplistener and able to send messages between each other successfully.
the problem is this:

when the client sends "[-]RF[-]" to the server, the server checks the incoming data, if it is "[-]RF[-]" then it sends back to the client the file name, for each file in the current working directory of the server.

after each filename, it sends that name back to the client, the client should recieve it... and it seems to do this.

however, it seems as if the client is recieving this in 1 big long string. This is not what I have told the server to do:

SERVER:


if(command.Equals("[-]RF[-]"))

{

string flagListSend = "";
flagListSend = "[-]Start[-]";
byte[] msg = System.Text.Encoding.ASCII.GetBytes(flagListSend);
this.SendMessageToClient(msg);
foreach(string sinthis.lstAudioFiles.Items)
{
msg = System.Text.Encoding.ASCII.GetBytes(s);
this.SendMessageToClient(msg);
}
flagListSend = "[-]Finish[-]";
msg = System.Text.Encoding.ASCII.GetBytes(flagListSend);
this.SendMessageToClient(msg);
}


the method "SendMessageToClient()" is just a method that uses the client Socket to send the message using the Socket.Send();

When the client recieves any kind of message it calls this method and processes the data the way I would like to. The client has this:


privatevoid HandleIncomingData(byte[] incomingData)

{

string dataFromServer = System.Text.Encoding.ASCII.GetString(incomingData, 0, incomingData.Length);
string properString =this.GetProperString(dataFromServer, "\0");
txtInfo.Text = txtInfo.Text + "Server: " + properString + " ";
if(properString.Equals("[-]Start[-]"))
{
string innerMsg = properString;
while (innerMsg.Equals("[-]Finish[-]") ==false)
{
byte[] innerIncomingData =newbyte[64];
int theData = ns.Read(innerIncomingData, 0, innerIncomingData.Length);
innerMsg =
this.GetProperString(System.Text.Encoding.ASCII.GetString(incomingData, 0, incomingData.Length), "\0");

if (innerMsg.Equals("[-]Finish[-]") ==false)
{
txtInfo.Text += "\n" + innerMsg;
cmbItems.Items.Add(innerMsg);
}
}
}
}

it doesnt seem to work. no items are being added to the combobox. I am basically trying to detect that if the incoming text is of a certain value then go into a loop and keep recieving items and add them to the combo box until a certain incoming data has been reached. once that data has been recieved ([-]Finish[-]) then it should exit the loop

It doesnt seem to be doing that. It's pretty tough to explain. (Asynchronous is not an option here unfortunatly)

The data I get shown in the txtInfo is the entire string concatinated.

any ideas? If you need clearer explanation let me know. I've been working on this for 2 days and i am really stuck.

[5845 byte] By [ahmedilyas] at [2007-12-16]
# 1
Your code assumes that the returned filenames are null-terminated strings, which they're not in .NET. Strings in .NET are unicode character arrays prefixed by the string length. Let's look at the contents of msg:

flagListSend = "[-]Start[-]";
byte[] msg = System.Text.Encoding.ASCII.GetBytes(flagListSend);

msg will look like this:
byte[] msg = new byte[] { '[', '-', ']', 'S', 't', 'a', 'r', 't', '[', '-', ']' };

There is no '\0' at the end, which is what your client code is expecting. Easiest solution is to append a trailing null.

What you're doing is quite low-level. You're also losing international characters as you're converting from Unicode (System.String) to ASCII. I would consider using a Web Service or even .NET Remoting. Then serialization would be taken care of for you by the framework. With a Web Service, you could write:

[WebService]
public class Jukebox : WebService {
[WebMethod]
public string[] GetSongs(int AlbumId) {
// Do something
return songs;
}
}
// WARNING: I just hacked the above code together in the textbox here. No guarentees this will even compile. Just trying to give you an example.

Then you could just bind the returned string[] to your databound controls.

JamesKovacs at 2007-9-9 > top of Msdn Tech,Visual C#,Visual C# General...
# 2
I see. Thanks very much.
Interesting. Wish I didnt need to really create a web service. I just want to notify the client "special data is coming"... the client then does certain things with that data until "end of special data" is sent from the server....
ahmedilyas at 2007-9-9 > top of Msdn Tech,Visual C#,Visual C# General...
# 3
You don't have to create a Web Service. I'm just saying that using higher-level protocols like .NET Remoting or Web Services is going to be faster to develop and less error-prone than thunking around at the sockets or TcpClient/Listener level.
JamesKovacs at 2007-9-9 > top of Msdn Tech,Visual C#,Visual C# General...
# 4
very true :) thanks!

Still one question remains, and i still do not follow:

when client sends server (or vica versa) a message like "hi"... it recieves it fully without a problem

that should be the same if I tell it to go thru each file in the current directory and send the file name... should be the same as sending a msg on its own (like a chat program)

I just dont understand why the client seems to get it as 1 big string. or maybe its just something im doing wrong (and i know that but dont know what)

this is the pseudo I have but dont think it will work:
client:

if startspecial == true
{
add item to combobox
}

if incoming msg = "start"
set startSpecial = true
if incoming msg = "finish"
set startSpecial = false;

ahmedilyas at 2007-9-9 > top of Msdn Tech,Visual C#,Visual C# General...
# 5

yup...dnt work

ahmedilyas at 2007-9-9 > top of Msdn Tech,Visual C#,Visual C# General...
# 6
You will be writing to the output stream fairly rapidly and you are writing raw bytes. When writing to sockets, there is no control flow such as start/end message. (Data is chunked into packets, but there is no control flow at the application level of the network stack.) On the client, you will receive everything that is available. Hence you see the whole message. You can re-code your processing to take this into account, but you'll have to be careful since any delay on the sending side (or while in transit) may mean that you may get the data in multiple chunks. You may also see different behavious depending on whether the client and server are on separate boxes or the same box and whether you have single or multiple processors. (I suspect that you're running both client and server on the same box during development.) This is why I would recommend using a higher level protocol as mentioned earlier. It worries about all the silly details of chunking data and reassembling.

To test this theory, you may want to try adding some:

System.Threading.Thread.CurrentThread.Sleep(1000);

to sleep your thread for 1 second after sending every line.

JamesKovacs at 2007-9-9 > top of Msdn Tech,Visual C#,Visual C# General...
# 7
I see. Thanks for that!
i was thinking about doing the sleep thing for the thread on the server side and did so but for 4 milliseconds (not long enough)

But I thought that this would really be ineffeciant and perhaps unprofessional and a cheap way of trying to do what I want

I will try the other way you mentioned. hope it works and I get it right!

i appreciate your time and help and has made it alot clearer :)

ahmedilyas at 2007-9-9 > top of Msdn Tech,Visual C#,Visual C# General...
# 8
I should have been clearer. Adding a Thread.CurrentThread.Sleep(1000) would be for testing purposes only. (i.e. To verify the theory that the client is buffering the incoming data before calling your function based on how quickly the data arrives.) You would definitely not want to do this in production code. Be wary of any code that uses timing tricks to make it work. Let's say you get it working with 1 second delay, but due to bad network congestion at some point, it takes 2 seconds and your code fails. You want to make your code robust in the face of varying packet arrival times.

I would strongly recommend to run your client and server on separate machines and investigate the behaviour. It might be different than running both on the same machine.

More than happy to assist. Happy coding.

JamesKovacs at 2007-9-9 > top of Msdn Tech,Visual C#,Visual C# General...
# 9
I understand completly, I would never use that code in the final application... only as testing/debugging purposes.

idea of a webservice is of course better - I can add more features to it easily. I wonder if it will work with .NET CF (retrieving webservices). Worth a shot for sure!

ahmedilyas at 2007-9-9 > top of Msdn Tech,Visual C#,Visual C# General...
# 10
Consuming Web Services with .NET CF definitely work. The only thing you have to watch out for is lack of support for WS-* specs. (WS-Security, WS-Addressing, etc.) (Note that you would need to be creating the Web Services in WSE or a similar toolkit. System.Web.Services doesn't support WS-* specs.) There is also limited ability to extend Web Services on CF. For instance, you can't use the GetWebRequest/Response() methods that exist in .NET Framework. You would need to do this if you wanted to enable compression of the SOAP packets.

If all you're doing is creating standard web services using System.Web.Services in .NET and consuming them from .NET CF, they definitely work. If you need additional functionality above and beyond what .NET CF offers, check out http://www.OpenNETCF.org, a free extension to .NET CF created by the .NET CF MVPs among others.

JamesKovacs at 2007-9-9 > top of Msdn Tech,Visual C#,Visual C# General...
# 11
Thanks for that :) I prefer to stick with the proper .NET framework rather than the opennetcf (even though it is .NET framework + additional classes etc...)

thanks alot for your help :)

ahmedilyas at 2007-9-9 > top of Msdn Tech,Visual C#,Visual C# General...
# 12
OpenNETCF is just an additional assembly built on top of .NET CF. No different than using any 3rd-party control. It's not replacing .NET CF in any way.
JamesKovacs at 2007-9-9 > top of Msdn Tech,Visual C#,Visual C# General...