从sockaddr结构获取IP和端口

前言

           从sockaddr结构中提取IP, 先将结构sockaddr转为sockaddr_in结构,然后用在利用相关API将其中的IP地址从网络格式转化我们熟悉点分十进制的字符串。

一、sockaddr和sockaddr_in结构

程序员不应操作sockaddr结构,sockaddr是给操作系统用的
程序员应使用sockaddr_in来表示地址,sockaddr_in区分了地址和端口,使用更方便。


struct sockaddr {  
    unsigned short    sa_family;    // 2 bytes address family, AF_xxx  unsiged short
    char              sa_data[14];     // 14 bytes of protocol address  
}; 
struct sockaddr_in {  
    short            sin_family;       // 2 bytes e.g. AF_INET, AF_INET6  
    unsigned short   sin_port;    // 2 bytes e.g. htons(3490)  
    struct in_addr   sin_addr;     // 4 bytes see struct in_addr, below  
    char             sin_zero[8];     // 8 bytes zero this if you want to  
};  
  
struct in_addr {  
    unsigned long s_addr;          // 4 bytes load with inet_pton()  
}; 

它们结构之间表示如下图。

 

二、从结构sockaddr获取IP和端口。

  使用结构inet_ntop获取IP地址,而不是用inet_ntoa。可能是因为64位机子引起的问题。

   详细的原因参考:https://blog.csdn.net/zmxiangde_88/article/details/8157256

 struct sockaddr from;
 /*
     ...
        working 
     ...
*/
 struct sockaddr_in *sock = ( struct sockaddr_in*)&from;
 int port = ntohs(sock->sin_port);
 #ifdef __MINGW32__  //windows上打印方式
	 printf("ip:port  %s : %d",inet_ntoa(sock->sin_addr),port);
 #else              //linux上打印方式
	struct in_addr in  = sock->sin_addr;
	char str[INET_ADDRSTRLEN];   //INET_ADDRSTRLEN这个宏系统默认定义 16
	//成功的话此时IP地址保存在str字符串中。
	inet_ntop(AF_INET,&in, str, sizeof(str));
	printf("ip:port  %s : %d",str,port);
 #endif

   inet_ntop接口文档

/* Convert a Internet address in binary network format for interface
   type AF in buffer starting at CP to presentation form and place
   result in buffer of length LEN astarting at BUF.  */
extern const char *inet_ntop (int __af, const void *__restrict __cp,
			      char *__restrict __buf, socklen_t __len)

将其转化的结果放置到buf中。即最终转化的IP值存放在buf中。

 

三、参考

       sockaddr和sockaddr_in的区别: https://blog.csdn.net/tao546377318/article/details/72780685
       inet_ntoa在64位机器上出错: https://blog.csdn.net/zmxiangde_88/article/details/8157256

       

发布了146 篇原创文章 · 获赞 247 · 访问量 48万+
展开阅读全文

C++socket获取ip地址问题

06-13

#include "stdafx.h" #include <Winsock2.h> #include <stdio.h> #include <iostream> #include <cstring> #include<ws2tcpip.h> #pragma comment(lib, "ws2_32.lib ") //linking to the library using namespace std; int main(int argc, char **argv) { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD(1, 1); err = WSAStartup(wVersionRequested, &wsaData);//initiate the ws2_32.dll and match the version if (err != 0) { return 0; } if (LOBYTE(wsaData.wVersion) != 1 || //if the version is not matched ,then quit and terminate the ws3_32.dll HIBYTE(wsaData.wVersion) != 1) { WSACleanup(); return 0; } struct addrinfo *ailist, *aip; struct addrinfo hint; struct sockaddr_in6 *sinp6; PHOSTENT hostinfo; char *hostname; //主机名 char *port = "3294"; //端口号 const char *addr; int ilRc; if (argv[1] = NULL) { gethostname(hostname, sizeof(hostname)); } else { hostname = argv[1]; } if ((hostinfo = gethostbyname(hostname)) == NULL) //获得本地ipv4地址 { errno = GetLastError(); fprintf(stderr, "gethostbyname Error:%d\n", errno); return 1; } LPCSTR ip; while (*(hostinfo->h_addr_list) != NULL) //输出ipv4地址 { ip = inet_ntoa(*(struct in_addr *) *hostinfo->h_addr_list); printf("ipv4 addr = %s\n\n", ip); hostinfo->h_addr_list++; } hint.ai_family = AF_INET6; hint.ai_socktype = SOCK_STREAM; hint.ai_flags = AI_PASSIVE; hint.ai_protocol = 0; hint.ai_addrlen = 0; hint.ai_canonname = NULL; hint.ai_addr = NULL; hint.ai_next = NULL; ilRc = getaddrinfo(hostname, port, &hint, &ailist); if (ilRc < 0) { char str_error[100]; strcpy(str_error, (char *)gai_strerror(errno)); printf("str_error = %s", str_error); return 0; } if (ailist == NULL) { printf("sorry not find the IP address,please try again \n"); } for (aip = ailist; aip != NULL; aip = aip->ai_next) { aip->ai_family = AF_INET6; sinp6 = (struct sockaddr_in6 *)aip->ai_addr; int i; printf("ipv6 addr = "); for (i = 0; i < 16; i++) { if (((i - 1) % 2) && (i>0)) { printf(":"); } printf("%02x", sinp6->sin6_addr.u.Byte[i]); } printf(" \n"); printf(" \n"); } system("pause"); return 0; } 代码如上,想实现的功能是从cmd进入后不输入参数输出本地ipv4 ipv6地址,输入域名可以输出指定域名的ipv4 ipv6地址 但是调试结果ipv6显示出错,全0,指定域名后也只会输出主机的地址,求各位大神看看,谢了 问答

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览