# Socket Problems

**URL:** <https://www.ruby-forum.com/t/socket-problems/190147>\
**Category:** Ruby\
**Created:** [June 17, 2010, 3:10am UTC](https://www.ruby-forum.com/t/socket-problems/190147 "2010-06-17T03:10:51Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![djames](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/7ab992/32.png) [@djames](https://www.ruby-forum.com/u/djames)\
**Post date:** [June 17, 2010, 3:10am UTC](https://www.ruby-forum.com/t/socket-problems/190147/1 "2010-06-17T03:10:51Z")

</div>

I want to use a Ruby script to connect to a vendor API. I have 2  
problems: 1) It takes almost a minute to establish a connection; and,  
2) after the connection is finally established, no data is returned in  
response to any requests. My test script which exhibits these problems  
is appended as Exhibit A. As part of my investigation into these  
problems, I put together a comparable PHP script. It is shown in  
Exhibit B and it works perfectly (i.e., it exhibits neither of these  
problems). In both scripts actual values are used for ‘ip’ and ‘port’.  
I’m really hoping that someone can tell me what I need to do to get my  
Ruby script working properly. TIA.

```
  ... doug

```

Exhibit - Malfunctioning Ruby Script

#!/opt/ruby-enterprise-1.8.6-20090610/bin/ruby

require ‘socket’  
login\_request=\<\<’\_ALTO’

\<?xml version="1.0" encoding="UTF-8" standalone="no"?\> client Login 135610 135610A1276479316B171 4bdee845b6e6dc67754b038f2b08bf74 \_ALTO socket=TCPSocket::new('ip','port') puts("Connect:\n"+socket.read()+"\n\n") socket.print(login\_request) puts("Login:\n"+socket.read()) response=socket.read() puts(response) socket.close

Exhibit B - Properly Functioning Comparable PHP Script

\<?php $login\_request=\< client Login 135610 135610A1276479316B171 4bdee845b6e6dc67754b038f2b08bf74 \_ALTO; $fp=fsockopen("ip",port); print("Connect:\n".fread($fp,1000)."\n\n"); fwrite($fp,$login\_request); print("Login:\n".fread($fp,1000)); fclose($fp); ?\>

---

<div class="post-metadata">

**Author:** ![djames](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/7ab992/32.png) [@djames](https://www.ruby-forum.com/u/djames)\
**Post date:** [June 17, 2010, 9:52am UTC](https://www.ruby-forum.com/t/socket-problems/190147/2 "2010-06-17T09:52:10Z")

</div>

Doug J. wrote:

> require ‘socket’

Socket.do\_not\_reverse\_lookup = true # speeds things up

> socket=TCPSocket::new(‘ip’,‘port’)  
> puts(“Connect:\n”+socket.read()+"\n\n")

Aside: port is usually an integer not a string (unless you’re giving a  
service name from /etc/services)

But the main problem is that socket.read will block until the other end  
drops the connection. You probably want socket.gets instead.

Other options include socket.readpartial(n) which will read _up to_ n  
bytes, which you may have to repeat until you have the whole response;  
or if the protocol is length-framed, then use e.g. socket.read(4) to  
read the length, followed by socket.read(len). But that doesn’t seem to  
be the case here.

I don’t know the semantics of fread($fp,1000) in PHP, but from your code  
I’d guess it doesn’t actually wait until 1000 bytes are available, but  
just reads up to 1000 bytes.

HTH,

Brian.

---

<div class="post-metadata">

**Author:** ![djames](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/7ab992/32.png) [@djames](https://www.ruby-forum.com/u/djames)\
**Post date:** [June 17, 2010, 4:22pm UTC](https://www.ruby-forum.com/t/socket-problems/190147/3 "2010-06-17T16:22:14Z")

</div>

Doug J. wrote:

> I want to use a Ruby script to connect to a vendor API. I have 2  
> problems: 1) It takes almost a minute to establish a connection; and,  
> 2) after the connection is finally established, no data is returned in  
> response to any requests.

IO#read will read until EOF unless you tell it how many bytes to read:

> puts(“Connect:\n”+socket.read()+"\n\n")

as you did in php:

---

<div class="post-metadata">

**Author:** ![djames](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/7ab992/32.png) [@djames](https://www.ruby-forum.com/u/djames)\
**Post date:** [June 20, 2010, 4:40am UTC](https://www.ruby-forum.com/t/socket-problems/190147/4 "2010-06-20T04:40:21Z")

</div>

I _FINALLY_ got this issue resolved! Brian, you were definitely on the  
right track with your suggestion that the ‘read’ method was the problem.  
However, the fix was to use the ‘recv’ method rather than the ‘gets’  
method. With that fix in place everything works perfectly just like the  
test PHP code. Thanks to all who contributed.

```
    ... doug
```

---

<div class="post-metadata">

**Author:** ![djames](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/7ab992/32.png) [@djames](https://www.ruby-forum.com/u/djames)\
**Post date:** [June 18, 2010, 10:01pm UTC](https://www.ruby-forum.com/t/socket-problems/190147/5 "2010-06-18T22:01:02Z")

</div>

> But the main problem is that socket.read will block until the other end  
> drops the connection. You probably want socket.gets instead.

Great suggestion. The problem seems to be that the xml returned by the  
host (which is php based) is not terminated with a new line. In fact,  
the returned xml contains no new lines at all. Consequently, using gets  
produces the same result as using read.

I’m thinking that the reason I’m having problems using Ruby to interface  
via a socket to a PHP based host is that each of the socket  
implementations in these two languages has slightly different  
expectations about the protocol being used to transmit the data. I’m  
not sure what the exact differences are. As you say, it does definitely  
seem that I am hung waiting for something while the PHP implementation  
seems to somehow know when the host is through transmitting the data.  
This hypothesis is supported by the fact that if I use readpartial and  
set the number of bytes to some low value less than the length of the  
data expected to be returned, I get a snappy response with the expected  
bytes of data. Also of interest is the fact that I can use telnet to  
interface to the PHP host and get a full response immediately. So,  
apparently telnet also knows how to tell when the host is through  
transmitting data.

I’m kind of surprised that there isn’t more chatter on this issue. I  
would think that it would have been frequently encountered by many  
others before me. I do know that it’s a BIG problem for me and I really  
need to find a fix.

> Aside: port is usually an integer not a string (unless you’re  
> giving a service name from /etc/services)

My bad. An integer obviously correct.

Thanks to all for the input. If anyone has any further ideas, I’d sure  
like to hear them.

```
    ... doug
```
