I've filed a bug 
http://ironruby.codeplex.com/WorkItem/View.aspx?WorkItemId=3122.

Thanks for the report and fix,
Tomas

-----Original Message-----
From: ironruby-core-boun...@rubyforge.org 
[mailto:ironruby-core-boun...@rubyforge.org] On Behalf Of ????????
Sent: Monday, November 16, 2009 12:45 AM
To: Ironruby-core
Subject: [Ironruby-core] IO#read for socket (SocketStream.cs)

Hello, I'm kenichi hashimoto.
I'm Japanese. I don't write english well.

-------------
I modified the IronRuby Libirary for reading from the socket to run the script 
of the druby-library.
The druby library is contained the standard ruby library.

[BACKGROUND]
I wrote two scripts that use the druby, and I tested it.
I saw a exception of the druby when a client script requested to the server 
script ( I wrote both the client and the server ) on the IronRuby 0.9.2.
This exception means that 'the druby library read the datum from the socket, 
but size is corrputed'.
Of course, this scripts is not occurred the exception in Matz Ruby
1.8.7 and 1.9.1.

[CAUSE]
I confirm that protocol of the druby and communication seq, I found the error 
that when the druby requests to read the socket with a size, sometimes the read 
methods return a data smaller than specify the read method.
The Ruby IO#Read( size ) MUST recive the buffer required size. If buffer is 
reached the request size, IO#read must block.


[INVESTIGATION]
I found the mistake in the
\ironruby\Merlin\Main\Languages\Ruby\Libraries.LCA_RESTRICTED\Socket\SocketStream.cs
.
"_socket.Receive" does NOT block to reach the request size.

        public override int Read(byte[] buffer, int offset, int count) {
            int bytesToRead = _peeked ? count - 1 : count;
            byte[] readBuffer = new byte[bytesToRead];
            long oldPos = _pos;

            if (bytesToRead > 0) {
                int bytesRead = _socket.Receive(readBuffer, bytesToRead, 
SocketFlags.None);
                _pos += bytesRead;
            }

I rewrote bellow:

            int updatedOffset = 0;
            while (bytesToRead > 0)
            {
                int bytesRead = 0;
                if (bytesToRead > 0)
                {
                    bytesRead = _socket.Receive(readBuffer, bytesToRead, 
SocketFlags.None);
                    _pos += bytesRead;
                    bytesToRead -= bytesRead;
                }

                if (_peeked)
                {
                    // Put the byte we've already peeked at the beginning of 
the buffer
                    buffer[offset] = _lastByteRead;
                    // Put the rest of the data afterwards
                    Array.Copy(readBuffer, 0, buffer, offset + 1 + 
updatedOffset, bytesRead);
                    _pos += 1;
                    _peeked = false;
                }
                else
                {
                    Array.Copy(readBuffer, 0, buffer, offset + updatedOffset, 
bytesRead);
                }
                updatedOffset += bytesRead;
            }

  Note:
    This code assumes the 'count > 0'.
    And I didn't consider about efficiency of the code.

If my consider is correct, Please modify this problem.

Thank you
B.R. Kenichi HASHIMOTO.
_______________________________________________
Ironruby-core mailing list
Ironruby-core@rubyforge.org
http://rubyforge.org/mailman/listinfo/ironruby-core

_______________________________________________
Ironruby-core mailing list
Ironruby-core@rubyforge.org
http://rubyforge.org/mailman/listinfo/ironruby-core

Reply via email to