Reputation: 6762
I came across this snippet of code which appeared in the guts of setting up a socket:
#define PORT xxxx
struct sockaddr_in self;
self.sin_family = PF_INET;
self.sin_port = htons(PORT);
I understand that we need to convert byte order of the data that we are transmitting over a network to Network Byte Order
but I don't get why we need to convert port number to that as well when setting up a socket. I mean, when we do bind, isn't it a "local" thing? Say the port we intend to be bound is 1 and the machine actually uses little endian; now since we converted it into Network Byte Order, wouldn't we be binding a totally different port to the socket?
Upvotes: 8
Views: 5448
Reputation: 2422
Are you asking why you the application programmer does it instead of the library doing it internally? If so, the only technical advantage I can think of is that it allows the application to do the conversion once and cache it and use it many times without requiring many conversions.
On TCP you only need to use it once per connection and typically won't make millions of connections. But on UDP you use it every time you send a packet, and it's reasonable to assume you'd make millions or billions of such calls.
Then, for myriad calls to say sendto()
for UDP, or what have you, the re-ordered-if-necessary address is supplied to the OS which can copy it as-is directly into outgoing network packets.
The alternative of doing it in the kernel would require every call to sendto()
to take what the app knows as the same address over and over, and reconvert it every time.
Since sendto()
benefits from this, that was perhaps sufficient reason for them to have the rest of the API work the same way.
Upvotes: 1
Reputation: 1174
Machines can use different encodings little/big endian. To standardize that you should use a uniform encoding when communicating through the network. That's why you have to convert the encoding to Network Byte Order regardless of it being little/big endian, what matters is that it is uniform and it is understood correctly by every device and software in the network.
Upvotes: 0
Reputation: 11453
The struct sockaddr_in
is just a wrapper structure for struct sockaddr
:
struct sockaddr {
unsigned short sa_family;
char sa_data[14];
};
The Port number and Ip-address are held together here. They are held together in sa_data[14]
- the first 2 bytes
holding the port number, and the next 4 bytes
holding the ip-address. The remaining 8 bytes
are unused. These are the 8 bytes
you clear to zeroes via sin_zero[8]
when you use sockaddr_in
.
This in entirety is sent via network, including the port number in network order.
Upvotes: 0
Reputation: 1970
I think let's assume you are using TCP. The port number is going to be in the packet header. That is going to be transmitted. So it will be in Network Byte Order.
Upvotes: 5
Reputation: 59997
You transmit the port number over the network. It is a part of the IP packet for TCP. Look up the RFC (ietf.org/rfc/rfc793.txt)
Upvotes: 0