[C#.NET Socket]BeginSend behaves unexpected.

Started by
18 comments, last by Annoyed 14 years, 10 months ago
Quote:To make it work in all cases I just have to pass identical fixed length parameters to the BeginSend and BeginReceive calls on the respective sides and this will lead to excessive bytes being transmitted


That won't work. Even if you pass 20 to BeginSend, and 20 to BeginReceive, at the other end, BeginReceive may end up only receiving 10 bytes, and the next BeginReceive might get 5 -- or might get 50, if there is more data pending. You have to treat a TCP stream as you would a file on disk, with the additional gnarl that the "receive" operation may return less than you asked for, even when the file isn't at the end.
enum Bool { True, False, FileNotFound };
Advertisement
As hplus stated. The best thing to do is ensure that each packet has an associated header giving the appropriate details about the packet, such as its length and type. When receiving you should buffer the data you have obtained until you have at least a full packet, which can then be dispatched to the appropriate handler.

Also, you should probably write a custom marshaling setup, using what you've demonstrated is not flexible and also has some rather nasty behavior under certain circumstances.

In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.

That may be, but in my case it does work coincidental or not.
But in any case I got the picture that I have to treat it as a stream :)
Quote:
The best thing to do is ensure that each packet has an associated header giving the appropriate details about the packet

As I am using structs and using the sequential structure layout. I set the first element of the struct to be a byte value that is unique per package type. Therefore by peeking the first byte i know what type of struct and also the size of it.
Not saying that it is the best solution.

Quote:
... using what you've demonstrated is not flexible and also has some rather nasty behavior under certain circumstances.

Care to elaborate?
Quote:Original post by Annoyed
Quote:
The best thing to do is ensure that each packet has an associated header giving the appropriate details about the packet

As I am using structs and using the sequential structure layout. I set the first element of the struct to be a byte value that is unique per package type. Therefore by peeking the first byte i know what type of struct and also the size of it.
Not saying that it is the best solution.

Pray tell: What do you do for chat messages? Send a fixed length buffer every time?
Quote:
... using what you've demonstrated is not flexible and also has some rather nasty behavior under certain circumstances.

Care to elaborate?
struct Stuff {  string Text {get;set;}}


Care to guess what this marshals to? I'll give you a hint question: Is string a value type or a reference type?

In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.

Quote:
Pray tell: What do you do for chat messages? Send a fixed length buffer every time?

yes, knowing that it is not optimal (at all).

Quote:
struct Stuff {  string Text {get;set;}}

Care to guess what this marshals to?

Nothing, there are no fields in your struct. But if there was a text field I would specify it as:
[StructLayout( LayoutKind.Sequential )]struct Packet{    [MarshalAs( UnmanagedType.ByValTStr, SizeConst = 256 )]    private string text;    public Stuff(string text)    {        this.text = text;    }}

Now it is marshalled as 256 char array.

Quote:
I'll give you a hint question: Is string a value type or a reference type?

It is a reference type. Your point?
Quote:Original post by Annoyed
Quote:
Pray tell: What do you do for chat messages? Send a fixed length buffer every time?

yes, knowing that it is not optimal (at all).

Quote:
struct Stuff {  string Text {get;set;}}

Care to guess what this marshals to?

Nothing, there are no fields in your struct. But if there was a text field I would specify it as:

Wrong, it does have a field. And it's a reference, marshals to sizeof(int*) relatively meaningless bytes.
Quote:
*** Source Snippet Removed ***
Now it is marshalled as 256 char array.

Indeed, and now you've got a problem in that you have no idea how many of those bytes you actually need. And for chat messages, that's damn important.

In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.

Ok I don't want to split hairs over what your uncompilable struct marshals into :)
And the importance you are referring to i presume is wasted bandwidth?
Because I don't need to know how many of the bytes I need because when I unmarshal it contains string as it was before it was marshaled.
But as I stated above I am aware it is not optimal.
Quote:Original post by Annoyed
Ok I don't want to split hairs over what your uncompilable struct marshals into :)

My "uncompilable" struct compiles quite fine if you're using the latest version of C#. [grin]
Quote:
And the importance you are referring to i presume is wasted bandwidth?
Because I don't need to know how many of the bytes I need because when I unmarshal it contains string as it was before it was marshaled.
But as I stated above I am aware it is not optimal.

True, it's a minor issue, and you have to remember to make sure you properly annotate all of your packet structures. Not to mention, a custom marshaller (actually, it would be a serializer), tends to be a lot more flexible in the data format of the packets, allowing for things like bitwise compression.

In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.

Quote:
My "uncompilable" struct compiles quite fine if you're using the latest version of C#. [grin]

I stand corrected >.<
Never saw that one before, gawd it saves tons of redundant coding.

Quote:Not to mention, a custom marshaller (actually, it would be a serializer), tends to be a lot more flexible in the data format of the packets, allowing for things like bitwise compression.

Yea that would be the best solution I agree. But again I'm just being lazy at picking the idea that happens more or less by it self.

This topic is closed to new replies.

Advertisement