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