# IO#read for socket (SocketStream.cs)

**URL:** <https://www.ruby-forum.com/t/io-read-for-socket-socketstream-cs/179038>\
**Category:** IronRuby\
**Created:** [November 16, 2009, 9:44am UTC](https://www.ruby-forum.com/t/io-read-for-socket-socketstream-cs/179038 "2009-11-16T09:44:52Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![SSSBSOS7SbSHS1SsSSS](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/df705f/32.png) [@SSSBSOS7SbSHS1SsSSS](https://www.ruby-forum.com/u/SSSBSOS7SbSHS1SsSSS)\
**Post date:** [November 16, 2009, 9:44am UTC](https://www.ruby-forum.com/t/io-read-for-socket-socketstream-cs/179038/1 "2009-11-16T09:44:52Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![SSSBSOS7SbSHS1SsSSS](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/df705f/32.png) [@SSSBSOS7SbSHS1SsSSS](https://www.ruby-forum.com/u/SSSBSOS7SbSHS1SsSSS)\
**Post date:** [November 16, 2009, 5:57pm UTC](https://www.ruby-forum.com/t/io-read-for-socket-socketstream-cs/179038/2 "2009-11-16T17:57:39Z")

</div>

I’ve filed a bug  
[http://ironruby.codeplex.com/WorkItem/View.aspx?WorkItemId=3122](http://ironruby.codeplex.com/WorkItem/View.aspx?WorkItemId=3122).

Thanks for the report and fix,  
Tomas

---

<div class="post-metadata">

**Author:** ![SSSBSOS7SbSHS1SsSSS](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/df705f/32.png) [@SSSBSOS7SbSHS1SsSSS](https://www.ruby-forum.com/u/SSSBSOS7SbSHS1SsSSS)\
**Post date:** [November 17, 2009, 6:29am UTC](https://www.ruby-forum.com/t/io-read-for-socket-socketstream-cs/179038/3 "2009-11-17T06:29:12Z")

</div>

Thank you for filing my report.

I forgot to attach my test scripts.(Sorry, it is NOT rubyspec.)  
I attach two test case that was used in my investigation work.

1. druby test case.

How to execute  
First c:\> ir.exe server.rb  
Second c:\> ir.exe client\_2.rb

client\_2.rb does NOT raise Exception in matz ruby.

1. TCPServer/TCPSocket test case.

How to execute  
First c:\> ir.exe s.rb  
Second c:\> ir.exe c.rb

c.rb does NOT display “false” line to console in matz ruby.

NOTE:  
I think that ‘0x0a’ char cause the problem of my report.  
Because, if buffer does NOT contain the ‘0x0a’ char, my socket program  
is success.  
I guess that below:  
1st:The writer program send a buffer (that contained the ‘0x0a’ char)  
to write socket stream, it do flush stream every ‘0x0a’ char.  
Next:The write socket stream send out a packet (that is splited by  
‘0x0a’ char) to a Network stack.  
Thus:The packet is fragmented, and the reader program receives a  
packet smaller than sent buffer.  
(Of course, the reader program can receive a remain data in the  
next API call.)

Thank you.  
B.R. Kenichi HASHIMOTO

2009/11/17 Tomas M. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

---

<div class="post-metadata">

**Author:** ![SSSBSOS7SbSHS1SsSSS](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/df705f/32.png) [@SSSBSOS7SbSHS1SsSSS](https://www.ruby-forum.com/u/SSSBSOS7SbSHS1SsSSS)\
**Post date:** [November 17, 2009, 7:23am UTC](https://www.ruby-forum.com/t/io-read-for-socket-socketstream-cs/179038/4 "2009-11-17T07:23:03Z")

</div>

Hashimoto-san, Thanks

I’ve attached your tests scripts and script explanation to the codeplex  
issue here:  
[http://ironruby.codeplex.com/WorkItem/View.aspx?WorkItemId=3122](http://ironruby.codeplex.com/WorkItem/View.aspx?WorkItemId=3122)

Best Regards,  
Kevin R.

2009/11/16 ã¯ã—ã‚‚ã¨ã‘ã‚“ã„ã¡ [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)
