详解IP地址格式转换:htonl/ntohl与inet_addr/inet_ntoa

需积分: 50 34 下载量 198 浏览量 更新于2024-09-08 2 收藏 4KB TXT 举报
本文档主要介绍了在VC++编程中常见的IP地址格式转换函数,以及主机字节序和网络字节序的概念。IP地址是互联网通信的基础,其表示形式通常为32位的二进制数,但为了便于传输和处理,经常采用点分十进制的形式。在计算机内部,数据的存储方式分为两种:主机字节序(Little Endian)和网络字节序(Big Endian),这会影响到不同平台间数据的正确交换。 1. htonl() 和 ntohl() 函数: - htonl() 函数(Host to Network Long)用于将32位的无符号长整型(u_long)数据从主机字节序转换为网络字节序,即将低字节移动到高位。例如,当你从用户输入或本地变量中获取一个IPv4地址(如0x01020304),通过htonl将其转换后,得到的是0x04030201,这是符合网络通信规范的。 - ntohl() 函数则相反,它将网络字节序的无符号长整型转换回主机字节序。如果收到的网络数据是0x04030201,通过ntohl解析后,你会得到原始的0x01020304。 2. inet_addr() 和 inet_ntoa() 函数: - inet_addr() 函数用于将一个字符串形式的IPv4地址(如"192.168.0.16")转换为无符号长整型(unsigned long),以便进行进一步的网络操作。在转换过程中,函数会检查输入的字符串是否符合IPv4地址的格式,并将其转换为对应的十进制数值,如0xC0A80001。 - inet_ntoa() 函数则是将32位的无符号长整型IP地址转换为点分十进制的字符串形式。例如,如果输入的是0xC0A80001,inet_ntoa会返回"192.168.0.16"。 这些函数在处理跨平台通信时尤为重要,因为不同的系统可能采用不同的字节序。在创建套接字(socket)、监听(listen)或绑定(bind)时,需要确保IP地址和端口的表示形式是网络字节序,以确保所有参与通信的系统能够正确解析。 另外,文档中提到的sockaddr结构体用于表示网络地址,其中包含了套接字的协议族(如AF_INET表示IPv4)、端口号、以及一个指向in_addr结构体的指针,后者用于存储32位的IP地址。sockaddr_in是针对IPv4的特殊版本,它包含一个IPv4地址字段,以及其他辅助信息。 理解并熟练运用这些IP地址格式转换函数,是编写跨平台网络程序的关键,尤其是在使用socket编程时,能够确保数据在网络中的正确传输和处理。
2011-02-22 上传
适合初学者 /******* 服务器程序 (server.c) ************/ #include <stdlib.h>; #include <stdio.h>; #include <errno.h>; #include <string.h>; #include <netdb.h>; #include <sys/types.h>; #include <netinet/in.h>; #include <sys/socket.h>; int main(int argc, char *argv[]) { int sockfd,new_fd; struct sockaddr_in server_addr; struct sockaddr_in client_addr; int sin_size,portnumber; char hello[]="Hello! Are You Fine?\n"; if(argc!=2) { fprintf(stderr,"Usage:%s portnumber\a\n",argv[0]); exit(1); } if((portnumber=atoi(argv[1]))<0) { fprintf(stderr,"Usage:%s portnumber\a\n",argv[0]); exit(1); } /* 服务器端开始建立socket 描述符 */ if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) { fprintf(stderr,"Socket error:%s\n\a",strerror(errno)); exit(1); } /* 服务器端填充 sockaddr 结构 */ bzero(&server_addr,sizeof(struct sockaddr_in)); server_addr.sin_family=AF_INET; server_addr.sin_addr.s_addr=htonl(INADDR_ANY); server_addr.sin_port=htons(portnumber); /* 捆绑sockfd 描述符 */ if(bind(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))== -1) { /******* 客户端程序 client.c ************/ #include <stdlib.h>; #include <stdio.h>; #include <errno.h>; #include <string.h>; #include <netdb.h>; #include <sys/types.h>; #include <netinet/in.h>; #include <sys/socket.h>; int main(int argc, char *argv[]) { int sockfd; char buffer[1024]; struct sockaddr_in server_addr; struct hostent *host; int portnumber,nbytes; if(argc!=3) { fprintf(stderr,"Usage:%s hostname portnumber\a\n",argv[0]); exit(1); } if((host=gethostbyname(argv[1]))==NULL) { fprintf(stderr,"Gethostname error\n"); exit(1); } if((portnumber=atoi(argv[2]))<0) { fprintf(stderr,"Usage:%s hostname portnumber\a\n",argv[0]); exit(1); } /* 客户程序开始建立 sockfd 描述符 */ if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) { fprintf(stderr,"Socket Error:%s\a\n",strerror(errno)); exit(1); } /* 客户程序填充服务端的资料 */ bzero(&server_addr,sizeof(server_addr)); server_addr.sin_family=AF_INET; server_addr.sin_port=htons(portnumber); server_addr.sin_addr=*((struct in_addr *)host->;h_addr); /* 客户程序发起连接请求 */ if(connect(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr) )==-1) { fprintf(stderr,"Connect Error:%s\a\n",strerror(errno)); exit(1); } /* 连接成功了 */ if((nbytes=read(sockfd,buffer,1024))==-1) { fprintf(stderr,"Read Error:%s\n",strerror(errno)); exit(1); } buffer[nbytes]='\0'; printf("I have received:%s\n",buffer); /* 结束通讯 */ close(sockfd); exit(0); }

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <unistd.h>int main() { int server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // 创建套接字 if (server_socket < 0) { perror("socket"); return 1; } struct sockaddr_in server_addr; server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htonl(INADDR_ANY); server_addr.sin_port = htons(8000); int iResult = bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)); // 绑定套接字 if (iResult < 0) { perror("bind"); close(server_socket); return 1; } iResult = listen(server_socket, SOMAXCONN); // 监听套接字 if (iResult < 0) { perror("listen"); close(server_socket); return 1; } printf("服务器已启动,等待连接...\n"); int counter = 0; while (1) { struct sockaddr_in client_addr; socklen_t client_addr_len = sizeof(client_addr); int client_socket = accept(server_socket, (struct sockaddr*)&client_addr, &client_addr_len); // 接受客户端连接 if (client_socket < 0) { perror("accept"); close(server_socket); return 1; } counter++; // 每当有一个新的客户端连接时,计数器加1 printf("客户端 %s:%d 已连接,是今天的第 %d 个客户端。\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port), counter); char reply[1024]; sprintf(reply, "你是今天第%d个客户端", counter); send(client_socket, reply, strlen(reply), 0); // 发送回复消息 close(client_socket); } close(server_socket); return 0;},在此代码基础上增加输出当前时间的功能

2023-06-10 上传