# Socket send functions only allow you to send strings?

**URL:** <https://rubytalk.org/t/socket-send-functions-only-allow-you-to-send-strings/40389>\
**Category:** ruby-talk\
**Created:** [4 September 2007 22:53 UTC](https://rubytalk.org/t/socket-send-functions-only-allow-you-to-send-strings/40389 "2007-09-04T22:53:10Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Ryan\_Parmeter](https://avatars.discourse-cdn.com/v4/letter/r/b19c9b/32.png) [@Ryan\_Parmeter](https://rubytalk.org/u/Ryan_Parmeter)\
**Post date:** [4 September 2007 22:53 UTC](https://rubytalk.org/t/socket-send-functions-only-allow-you-to-send-strings/40389/1 "2007-09-04T22:53:10Z")

</div>

I am writing a small TimeP (RFC 868) server to sync time with some  
networking equipment. The equipment that shall go nameless requires the  
use of UDP.

As far as I can tell, my only option to write to a UDPSocket is to use  
the send method, which takes a string. I need to send a 32bit integer  
representing the date in a UDP packet and I'd love to use something  
like:

myUDPsocket.send( Time.now.to\_i, 0, host, port)

In my situation I can't change the receiving program to accept a string  
or I could do it that way. I can't convert the integer to a string  
either because that would blow my 32 bit requirement. Does anyone have  
any idea?

~Parkingmeter

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

**Author:** ![Patrick\_Hurley1](https://avatars.discourse-cdn.com/v4/letter/p/b77776/32.png) [@Patrick\_Hurley1](https://rubytalk.org/u/Patrick_Hurley1)\
**Post date:** [4 September 2007 22:59 UTC](https://rubytalk.org/t/socket-send-functions-only-allow-you-to-send-strings/40389/2 "2007-09-04T22:59:44Z")

</div>

Try

ri Array#pack

[number].pack('i')

should do the trick.  
pth

> **···**
>
> On 9/4/07, Ryan Parmeter \<parkingmeter@gmail.com\> wrote:
> 
> > I am writing a small TimeP (RFC 868) server to sync time with some  
> > networking equipment. The equipment that shall go nameless requires the  
> > use of UDP.
> > 
> > As far as I can tell, my only option to write to a UDPSocket is to use  
> > the send method, which takes a string. I need to send a 32bit integer  
> > representing the date in a UDP packet and I'd love to use something  
> > like:
> > 
> > myUDPsocket.send( Time.now.to\_i, 0, host, port)
> > 
> > In my situation I can't change the receiving program to accept a string  
> > or I could do it that way. I can't convert the integer to a string  
> > either because that would blow my 32 bit requirement. Does anyone have  
> > any idea?
> > 
> > ~Parkingmeter  
> > --  
> > Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

**Author:** ![Joel\_VanderWerf1](https://avatars.discourse-cdn.com/v4/letter/j/94ad74/32.png) [@Joel\_VanderWerf1](https://rubytalk.org/u/Joel_VanderWerf1)\
**Post date:** [4 September 2007 23:05 UTC](https://rubytalk.org/t/socket-send-functions-only-allow-you-to-send-strings/40389/3 "2007-09-04T23:05:41Z")

</div>

Ryan Parmeter wrote:

> I am writing a small TimeP (RFC 868) server to sync time with some  
> networking equipment. The equipment that shall go nameless requires the  
> use of UDP.
> 
> As far as I can tell, my only option to write to a UDPSocket is to use  
> the send method, which takes a string. I need to send a 32bit integer  
> representing the date in a UDP packet and I'd love to use something  
> like:
> 
> myUDPsocket.send( Time.now.to\_i, 0, host, port)
> 
> In my situation I can't change the receiving program to accept a string  
> or I could do it that way. I can't convert the integer to a string  
> either because that would blow my 32 bit requirement. Does anyone have  
> any idea?

Strings are just blobs of binary data, when they go through #send. The receiver doesn't know it started life as a ruby string.

If you want structure, use #pack. You'll need to know what byte-order the client and server should use to communicate. Assuming big-endian:

myUDPsocket.send([Time.now.to\_i].pack("N"), 0, host, port)

> **···**
>
> --  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

---

<div class="post-metadata">

**Author:** ![Kirk\_Haines](https://avatars.discourse-cdn.com/v4/letter/k/c6cbf5/32.png) [@Kirk\_Haines](https://rubytalk.org/u/Kirk_Haines)\
**Post date:** [4 September 2007 23:07 UTC](https://rubytalk.org/t/socket-send-functions-only-allow-you-to-send-strings/40389/4 "2007-09-04T23:07:37Z")

</div>

A string is just a sequence of bytes. It can be anything.

In your case, you need to encode a decimal number as returned by Time.now.to\_i into 32 bits.

myUDPsocket.send( [Time.now.to\_i].pack('i') )

That may be what you need.

[http://ruby-doc.org/core/classes/Array.html#M002245](http://ruby-doc.org/core/classes/Array.html#M002245)

For more information.

Kirk Haines

> **···**
>
> On Wed, 5 Sep 2007, Ryan Parmeter wrote:
> 
> > As far as I can tell, my only option to write to a UDPSocket is to use  
> > the send method, which takes a string. I need to send a 32bit integer  
> > representing the date in a UDP packet and I'd love to use something  
> > like:
> > 
> > myUDPsocket.send( Time.now.to\_i, 0, host, port)
> > 
> > In my situation I can't change the receiving program to accept a string  
> > or I could do it that way. I can't convert the integer to a string  
> > either because that would blow my 32 bit requirement. Does anyone have  
> > any idea?

---

<div class="post-metadata">

**Author:** ![See](https://avatars.discourse-cdn.com/v4/letter/s/c68b51/32.png) [@See](https://rubytalk.org/u/See)\
**Post date:** [5 September 2007 03:40 UTC](https://rubytalk.org/t/socket-send-functions-only-allow-you-to-send-strings/40389/5 "2007-09-05T03:40:54Z")

</div>

In article \<63fd7d04f963970925560990c6583e9d@ruby-forum.com\>,  
Ryan Parmeter \<parkingmeter@gmail.com\> writes:

> I am writing a small TimeP (RFC 868) server to sync time with some  
> networking equipment. The equipment that shall go nameless requires the  
> use of UDP.
> 
> As far as I can tell, my only option to write to a UDPSocket is to use  
> the send method, which takes a string. I need to send a 32bit integer  
> representing the date in a UDP packet and I'd love to use something  
> like:
> 
> myUDPsocket.send( Time.now.to\_i, 0, host, port)
> 
> In my situation I can't change the receiving program to accept a string  
> or I could do it that way. I can't convert the integer to a string  
> either because that would blow my 32 bit requirement. Does anyone have  
> any idea?
> 
> ~Parkingmeter

Here, I had this script lying about from one of my earlier experiments  
with Ruby sockets:

- dmw

------ start of code -------  
#! /usr/bin/env ruby

# nettimesvr.rb - implement Time Server for RFC 868

PROGNAME = 'nettimesvr.rb'  
timeport = Socket.getservbyname('time', 'udp') # port 37  
# timeport = 50037 # for testing  
RFC868\_POSIX\_ADJMENT = 2\_208\_988\_800 # diff between RFC 868 and POSIX  
POSIX\_EPOCH\_ADJMENT = Time.gm(1970, 'Jan', 1).to\_i

require 'socket'

def curnettime()  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return Time.new.to\_i + (RFC868\_POSIX\_ADJMENT - POSIX\_EPOCH\_ADJMENT)  
end

port = timeport  
begin  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case ARGV.size  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;when 1: port = Integer(ARGV[0])  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;when 0: nil  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else; abort "Usage: #{PROGNAME} [port]"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
rescue ArgumentError =\> badarg  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;abort "Argument conversion error: #{badarg}"  
end

puts "Listening on port #{port}\n"

UDPSocket.open { |sock|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sock.bind(Socket::INADDR\_ANY, port)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;loop do  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# if we try to receive zero bytes, we get an error  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rmthost = sock.recvfrom(1) [1] # no body expected  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts "Accepted request from #{rmthost [2]}"

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nettime = [curnettime()].pack('N')  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sock.send(nettime, 0, rmthost[2], rmthost[1])  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
}

------ end of code -------

> **···**
>
> --  
> . Douglas Wells . Connection Technologies .  
> . Internet: -sp9804- -at - contek.com- .

---

<div class="post-metadata">

**Author:** ![Francis\_Cianfrocca](https://avatars.discourse-cdn.com/v4/letter/f/7bcc69/32.png) [@Francis\_Cianfrocca](https://rubytalk.org/u/Francis_Cianfrocca)\
**Post date:** [5 September 2007 00:46 UTC](https://rubytalk.org/t/socket-send-functions-only-allow-you-to-send-strings/40389/6 "2007-09-05T00:46:10Z")

</div>

Actually, to support RFC-868, you have to use the same epoch that NTP uses,  
rather than the Unix epoch.

The current time in raw form would be Time.now.to\_i + 0x83aa7e80. Pack into  
32 bits (taking care to keep the conversion unsigned), convert to  
network-order as necessary, write a four-byte UDP datagram, and away you go.

> **···**
>
> On 9/4/07, khaines@enigo.com \<khaines@enigo.com\> wrote:
> 
> > On Wed, 5 Sep 2007, Ryan Parmeter wrote:
> > 
> > \> As far as I can tell, my only option to write to a UDPSocket is to use  
> > \> the send method, which takes a string. I need to send a 32bit integer  
> > \> representing the date in a UDP packet and I'd love to use something  
> > \> like:  
> > \>  
> > \> myUDPsocket.send( Time.now.to\_i, 0, host, port)  
> > \>  
> > \> In my situation I can't change the receiving program to accept a string  
> > \> or I could do it that way. I can't convert the integer to a string  
> > \> either because that would blow my 32 bit requirement. Does anyone have  
> > \> any idea?
> > 
> > A string is just a sequence of bytes. It can be anything.
> > 
> > In your case, you need to encode a decimal number as returned by  
> > Time.now.to\_i into 32 bits.
> > 
> > myUDPsocket.send( [Time.now.to\_i].pack('i') )
> > 
> > That may be what you need.
> > 
> > [class Array - RDoc Documentation](http://ruby-doc.org/core/classes/Array.html#M002245)
> > 
> > For more information.
> > 
> > Kirk Haines
