Bug 16021 - Setting ReceiveBufferSize & SendBufferSize on TcpClient or Socket doesn't have the desired affect
Summary: Setting ReceiveBufferSize & SendBufferSize on TcpClient or Socket doesn't hav...
Status: RESOLVED FIXED
Alias: None
Product: Class Libraries
Classification: Mono
Component: System ()
Version: 3.2.x
Hardware: PC Linux
: --- normal
Target Milestone: Untriaged
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2013-11-07 17:47 UTC by Narinder
Modified: 2014-07-29 08:01 UTC (History)
4 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:


Attachments
Two project to reproduce the undesired behaviour (6.32 KB, application/zip)
2013-11-07 17:47 UTC, Narinder
Details


Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on GitHub or Developer Community with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED FIXED

Description Narinder 2013-11-07 17:47:42 UTC
Created attachment 5365 [details]
Two project to reproduce the undesired behaviour

Mono: 3.2.3
OS: Debian Wheezy

Setting the properties ReceiveBufferSize & SendBufferSize on either TcpClient OR Socket does not appear to have the desired affect. 

Regardless of the values that these properties are set to, on reading these properties back, always the same number is returned, regardless of the values they were attempted to be set to. HOWVEVER the constant values that the properties get set to, seems to vary on different machines. I tried on two physically different Debian boxes and the the constant was different.

Moreover the values read from these properties after attempting to set them is not equal to the values read from the properties when not having attempted to set them.

Depending on the constant on a particular machine this can/has been a serious performance issue. Specifically on one of the Debian Prod machines a values of 128 * 1024 was assigned to these properties, but they were in fact set to about 2000 bytes.

Code to replicate the issue is attached. The solution contains a Server project and a Client Project. The Client repeatedly sends largish (128 * 1024) byte arrays to the server. The server reads the sent data from the Network Stream and displays the size of each array of bytes received. 
In the source file Program.cs in the project Server the two lines    :

            //client.ReceiveBufferSize = 128 * 1024;
            //client.SendBufferSize = 128 * 1024;

can be toggled to see the differing behaviour.

Rgds
N
Comment 1 Narinder 2013-11-07 18:30:02 UTC
After digging a little, I suspect that this issue is related to :
https://bugzilla.xamarin.com/show_bug.cgi?id=12754
Comment 2 Narinder 2013-11-08 05:49:08 UTC
Latest finding:
In file mcs/class/System/System.Net.Sockets/Socket_2_1.cs

you can find the following method :

[MethodImplAttribute(MethodImplOptions.InternalCall)]
		private extern static void SetSocketOption_internal (IntPtr socket, SocketOptionLevel level,
								     SocketOptionName name, object obj_val,
								     byte [] byte_val, int int_val,
								     out int error);

		public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, int optionValue)
		{
			if (disposed && closed)
				throw new ObjectDisposedException (GetType ().ToString ());

			int error;

optionValue = " + optionValue.ToString());
			SetSocketOption_internal (socket, optionLevel, optionName, null,
						 null, optionValue, out error);

			if (error != 0)
				throw new SocketException (error);
		}


Changing this code by inserting one, not so obvious line SOLVES the issue.

[MethodImplAttribute(MethodImplOptions.InternalCall)]
		private extern static void SetSocketOption_internal (IntPtr socket, SocketOptionLevel level,
								     SocketOptionName name, object obj_val,
								     byte [] byte_val, int int_val,
								     out int error);

		public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, int optionValue)
		{
			if (disposed && closed)
				throw new ObjectDisposedException (GetType ().ToString ());

			int error;

			Console.WriteLine("Socket_2_1.cs SetSocketOption optionValue = " + optionValue.ToString());
			SetSocketOption_internal (socket, optionLevel, optionName, null,
						 null, optionValue, out error);

			if (error != 0)
				throw new SocketException (error);
		}

Why it solves the issue is a complete mystery !

Rgds
N
Comment 3 Narinder 2013-11-08 05:51:06 UTC
.. in the comment above in the first paste of code the string

"optionValue = " + optionValue.ToString());"

should not be there.
Comment 4 Narinder 2013-11-08 06:13:16 UTC
..and yet a little more investigation reveals that leaving mcs/class/System/System.Net.Sockets/Socket_2_1.cs untouched but modifying /mono/metadata/socket-io.c such that the code :

void ves_icall_System_Net_Sockets_Socket_SetSocketOption_internal(SOCKET sock, gint32 level, gint32 name, MonoObject *obj_val, MonoArray *byte_val, gint32 int_val, gint32 *error)
{
	struct linger linger;
	int system_level;
	int system_name;
	int ret;



is changed to 


void ves_icall_System_Net_Sockets_Socket_SetSocketOption_internal(SOCKET sock, gint32 level, gint32 name, MonoObject *obj_val, MonoArray *byte_val, gint32 int_val_in, gint32 *error)
{
	struct linger linger;
	int system_level;
	int system_name;
	int ret;
	int int_val = int_val_in;



Fixes the issue.



Rgds
N
Comment 5 Andres G. Aragoneses 2013-11-08 10:42:38 UTC
> untouched but modifying socket-io.c such that the code :

It is more clear if you can attach such changes in DIFF format.

And bonus points if you propose your change as a pull request in github (this way it's less work for maintainers to merge your fix).
Comment 6 Narinder 2013-11-08 14:56:56 UTC
I intended to, however I am unable to git clone the tree at work so will have to wait until I am at home.

I have finally managed to resolve my issue. It was in fact already solved by Benoit on this bug :

https://bugzilla.xamarin.com/show_bug.cgi?id=12754

I initially misunderstood his post. 

Rgds
N
Comment 7 Andres G. Aragoneses 2013-11-08 15:44:18 UTC
>It was in fact already solved by Benoit on this bug

Benoit didn't post a patch in DIFF form either, can you create a patch on behalf of him? Thanks
Comment 8 Narinder 2013-11-08 16:28:02 UTC
Yes.
Comment 9 Narinder 2013-11-08 20:12:26 UTC
I have initiated a Pull request entitled :

Setting ReceiveBufferSize & SendBufferSize on Socket (Bug 16021 & Bug 12754)

https://github.com/mono/mono/pull/801



Rgds
N