[comp.sys.encore] getsockname problem ??

pcb@gator.cacs.usl.edu (Peter C. Bahrs) (05/04/90)

I am porting some socket stuff from the SUN 3's to the Encore.

The code makes a call to : getsockname (socket, (struct sockaddr*) ptr, &len)
where ptr is of type sockaddr_in.  This seems to work fine on the SUN and
on the VAX and the RT.  I am trying to reference the field :
   ptr->sin_port which is a numeric.  I want to:
sprintf (buff, "%d", ptr->sin_port);
Like I said, it works fine on SUN and VAX but puts some wierd stuff in their
for the Encore.  The weird stuff is not the same port ID as was created.
I doing something non portable?

Encore BSD 4.2, SUN & VAX 4.3


/*----------- Thanks in advance... --------------------------------------+
| Peter C. Bahrs                                                         |
| The USL-NASA Project                                                   |
| Center For Advanced Computer Studies      INET: pcb@gator.cacs.usl.edu |
| 2 Rex Street                                                           |
| University of Southwestern Louisiana      ...!uunet!dalsqnt!gator!pcb  | 
| Lafayette, LA 70504                                                    |
+-----------------------------------------------------------------------*/

jik@athena.mit.edu (Jonathan I. Kamens) (05/04/90)

(NOTE: I don't read comp.sys.encore, so I don't know if this question
has already been answered.  Also, I feel that the question is of general
interest to Unix programmers, and reveals something important about
using network code on *any* Unix platform, so I am posting to both
comp.sys.encore and comp.unix.questions.)

In article <7889@rouge.usl.edu>, pcb@gator.cacs.usl.edu (Peter C. Bahrs)
writes:
|> The code makes a call to : getsockname (socket, (struct sockaddr*)
ptr, &len)
|> where ptr is of type sockaddr_in.  This seems to work fine on the SUN and
|> on the VAX and the RT.  I am trying to reference the field :
|>    ptr->sin_port which is a numeric.  I want to:
|> sprintf (buff, "%d", ptr->sin_port);
|> Like I said, it works fine on SUN and VAX but puts some wierd stuff in their
|> for the Encore.  The weird stuff is not the same port ID as was created.
|> I doing something non portable?

  The important thing to realize here is that port numbers and addresses
are stored in struct sockaddr_in structures in network byte order. 
Therefore, *whenever* you want to use the sin_port or sin_addr.s_addr
component of a sockaddr_on, you have to convert it from network byte
order to host byte order, and whenever you want to store a value into
the sin_port field of the sockaddr_in (or store a constant address into
the sin_addr.s_addr field, although this type of thing is frowned upon,
since you should use gethostbyname() and then assign the return value
directly into the sin_addr.s_addr field), you have to convert the number
from host byte order into network byte order before doing the assignment.

  The functions you use to do this are htons(), htonl(), ntohs() and
ntohl().  The first two convert host shorts and host longs to network
shorts and network longs, and the second two do the opposite.  There
should be man pages for these functions on your systems.

  A couple notes:

1. Theoretically, byte order may not be all that makes your machine's number
   representation different from network byte order representation, and
   the hton* and ntoh* functions will take care of other differences, but
   *I've* never worked on a machine where anything besides byte order
   matters :-).

2. On machines where network byte order and host byte order are the same, the
   four functions I've mentioned are supposed to be declared as null macros in
   the header file that declares them (on my system, they're declared in
   <netinet/in.h>).

Jonathan Kamens			              USnail:
MIT Project Athena				11 Ashford Terrace
jik@Athena.MIT.EDU				Allston, MA  02134
Office: 617-253-8495			      Home: 617-782-0710

jik@athena.mit.edu (Jonathan I. Kamens) (05/04/90)

In article <20328:May402:03:4790@stealth.acf.nyu.edu>, 
brnstnd@stealth.acf.nyu.edu writes:
|> In article <1990May3.233332.5956@athena.mit.edu> jik@athena.mit.edu
|> (Jonathan I. Kamens) writes:
|> > (or store a constant address into
|> > the sin_addr.s_addr field, although this type of thing is frowned upon,
|> > since you should use gethostbyname() and then assign the return value
|> > directly into the sin_addr.s_addr field),
|> Don't be so pedantic. All programs should accept both numeric addresses
|> and domain names.

  Definitely.  You're misreading what I said.  If a program is given a
numeric address, then it uses inet_addr() (which is, IMHO, in the same
class as gethostbyname().  I meant to say "something like
gethostbyname()" in my message, not just "gethostbyname()", and perhaps
that's why you misunderstood me) to convert it into a network byte
order, and then assings that to the sin_addr.s_addr field.

  When I said "constant address", I was talking about unsigned long
integers hard-coded into a program.  This is the "type of thing" I
consider to be "frowned upon."

Jonathan Kamens			              USnail:
MIT Project Athena				11 Ashford Terrace
jik@Athena.MIT.EDU				Allston, MA  02134
Office: 617-253-8495			      Home: 617-782-0710

brnstnd@stealth.acf.nyu.edu (05/04/90)

A note of warning: In a struct servent (as read from /etc/services),
s_port is defined as an int. Don't pass it to ntohl()! All ports are
unsigned short values and should go through ntohs().

In article <1990May3.233332.5956@athena.mit.edu> jik@athena.mit.edu (Jonathan I. Kamens) writes:
> (or store a constant address into
> the sin_addr.s_addr field, although this type of thing is frowned upon,
> since you should use gethostbyname() and then assign the return value
> directly into the sin_addr.s_addr field),

Don't be so pedantic. All programs should accept both numeric addresses
and domain names.

---Dan