[Mono-dev] .NET Remoting: Upload of a file from a Win32 MS .NET client to a Linux Mono .NET server.

Robert Jordan robertj at gmx.net
Fri Sep 2 09:22:56 EDT 2005


Yngve,

> The problems (now) arise when i try to upload a zip file from 
> the client to the server.
> I use a parameter with a (File)Stream object to do "callbacks" 
> to Read the file in blocks from the client into the server.
> When calling the Read(buffer, 0, buffer.Length) method 
> I get index out of range exception messages on my the Mono server.
> 
> Here is the code snippet for a simplified test example : 
> 
> public class RemoteObject : MarshalByRefObject
> {
> 
>   ...
> 
>   // AFAIK not more than 350 Kb can be serialized in .NET.
>   //private const int PORTION_SIZE = (256 * 1024);
>   //private const int PORTION_SIZE = 1024;
>   private const int PORTION_SIZE = 64;
> 
>   ...
> 
>   /// <summary>
>   /// Method FileUpload to test the remoting.
>   /// </summary>
>   public bool FileUpload(Stream fileIn, long fileInLength)
>   {
> 	bool returnValue = false;
> 	// Download large files in shunks.
> 	long bytesDownloadedIn = 0L;
> 	FileStream fileOut = new FileStream("FileOut.txt",
> 		FileMode.OpenOrCreate, FileAccess.Write);
> 	long bytesDownloadedOut = 0L;
> 	try 
> 	{
> 		for (bytesDownloadedIn = 0L; bytesDownloadedIn < 			fileInLength; )
> 		{
> 			// request the next portion
> 			int sizeToRead = (int)Math.Min(PORTION_SIZE, 				fileInLength -
> bytesDownloadedIn);


since bytesDownloadedId is 0 in the first loop,
sizeToRead will be 0 as well.


> 			byte[] buffer = new byte[sizeToRead];
> 			fileIn.Read(buffer, 0, buffer.Length);	//<err>	 			// update counters


Well, you're reading 0 bytes. The current Mono runtime
doesn't throw an exception any more.
Which Mono version are you using?

> Can anyone advice me how I should do to upload 
> a file from Win32 MS .NET to Linux Mono .NET.
> The issue is critical to get my application to work on Mono.
> Is there some other stream class I can use to transfer 
> a file from the client to the server.

Using a Stream as an argument for a remoting method
is pretty bad, since Stream is quite chatty. You'll end up
having a lot of traffic between client and server.

Additionaly, because Streams are MarshalByRef objects,
the server will callback into the client giving you
a lot of trouble with firewalls.

You may try this chunky approach (untested):


Hashtable handles = new HashTable ();
Random rng = new Random ();

public int Open ()
{
     int handle;
     do {
         handle = rng.Next ();
     } while (handles.Contains (handle);

     handles [handle] = File.OpenWrite (....);
     return handle;
}

public void Write (int handle, byte[] data, int offset, int count)
{
     Stream stm = handles [handle] as Stream;
     if (stm == null) throw new IOException ("no such handle");
     stm.Write (data, offset, count)
}

public void Close (int handle)
{
     Stream stm = handles [handle] as Stream;
     if (stm == null) throw new IOException ("no such handle");
     stm.Close ();
     handles.Remove (stm);
}


> As an aside I also want to report back the progress 
> of the file upload to the client.
> I want to update a progressbar on my Win32 client. 
> I have succeded to do that on my pure Win32 application, 
> though some progressbar handling technique.
> Am I expected to get any trouble using the ProgressBar 
> indirectly as a method parameter?.

Don't do that. Use the chunky approach above so you can
update the progress bar on the client. Even w/out the
chunky stuff, you should always use threads on the client
for time consuming operations. With some care (use the Invoke
method) you can update the ProgressBar from the upload thread.

Rob




More information about the Mono-devel-list mailing list