2013-10-06 42 views
25

我是套接字编程的新手,我试图理解htons()的操作。我已经阅读了互联网上的一些教程,例如thisthis。但我无法理解htons()究竟做了什么。我尝试下面的代码:套接字编程中的htons()函数

#include <stdio.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 

int main(int argc, char *argv[]) 
{ 
    int sockfd, newsockfd, portno, clilen; 
    char buffer[256]; 
    struct sockaddr_in serv_addr, cli_addr; 
    int n; 

    /* First call to socket() function */ 
    sockfd = socket(AF_INET, SOCK_STREAM, 0); 
    if (sockfd < 0) 
    { 
     perror("ERROR opening socket"); 
     exit(1); 
    } 
    /* Initialize socket structure */ 
    bzero((char *) &serv_addr, sizeof(serv_addr)); 
    portno = 5001; 
    serv_addr.sin_family = AF_INET; 
    serv_addr.sin_addr.s_addr = INADDR_ANY; 
    serv_addr.sin_port = htons(portno); 

    /* Now bind the host address using bind() call.*/ 
    if (bind(sockfd, (struct sockaddr *) &serv_addr, 
          sizeof(serv_addr)) < 0) 
    { 
     perror("ERROR on binding"); 
     exit(1); 
    } 

    /* Now start listening for the clients, here process will 
    * go in sleep mode and will wait for the incoming connection 
    */ 
    listen(sockfd,5); 
    clilen = sizeof(cli_addr); 

    /* Accept actual connection from the client */ 
    newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, 
           &clilen); 
    if (newsockfd < 0) 
    { 
     perror("ERROR on accept"); 
     exit(1); 
    } 
    /* If connection is established then start communicating */ 
    bzero(buffer,256); 
    n = read(newsockfd,buffer,255); 
    if (n < 0) 
    { 
     perror("ERROR reading from socket"); 
     exit(1); 
    } 
    printf("Here is the message: %s\n",buffer); 

    /* Write a response to the client */ 
    n = write(newsockfd,"I got your message",18); 
    if (n < 0) 
    { 
     perror("ERROR writing to socket"); 
     exit(1); 
    } 
    return 0; 
} 

sin_port的值显示为35091在调试时,我不知道如何改变portno500135091。有人可以解释价值变化的原因吗?

+1

你对什么是htons()有什么了解?你读过这个:http://en.wikipedia.org/wiki/Endianness。 –

+0

根据Linux手册'htons()'函数将无符号短整数主机从主机字节顺序转换为网络字节顺序。 – Shushant

+0

我知道大Endianne和小Endianne,但我不知道htons()正确的操作! – User123422

回答

20

htonshost-to-network short

这意味着它可以在16位的短整数。即2个字节。

此函数交换短的字节序。

0001 0011 1000 1001 = 5001

当字节顺序发生了变化,交换两个字节:

1000 1001 0001 0011 = 35091

+0

你的意思是0001 0011是主机字节,1000 1001是网络版本? – User123422

+1

@ User123422不行,你错了。即使 - 虽然5001的二进制形式是“'0001 0011''1000 1001'”,但将它存储在LittleEndian机器中时,它将以相反的顺序(“'1000 1001''0001 0011'”)存储字节。想想这个;如果'A'和'B'分别代表8位,则二进制数字'AB'将被存储为LittleEndian机器中的'BA'(如果您需要知道原因,则可将其存储为“Google Endianness”)。 'htons()'是一个方便的函数,用于将任何给定的短语转换为BigEndian格式('AB'格式),因为这是'网络字节顺序'。 – Anubis

3

htons()功能的主机和网络字节之间转换值

您的号码在开出命令。 big-endianlittle-endian和网络字节顺序有所不同,具体取决于您所使用的机器和网络协议。

67

它与字节存储在内存中的顺序有关。十进制数5001为十六进制的0x1389,所涉及的字节数为0x130x89。许多设备存储数字little-endian格式,这意味着最低有效字节首先。因此,在这个特定的例子这意味着在内存中的数字5001将被存储为

0x89 0x13 

htons()函数确保数字存储在网络字节顺序,这是最显著字节第一存储器。因此,将交换构成数个字节,使得在存储器中的字节将被存储在顺序

0x13 0x89 

在一个小端机,对换字节数是0x8913十六进制的,其中以十进制表示法为35091。请注意,如果您正在使用big-endian机器,则htons()函数不需要进行任何交换,因为编号已经以正确的方式存储在内存中。

所有这些交换的根本原因与使用中的网络协议有关,它们要求传输的数据包使用网络字节顺序。