2012-10-10 270 views
7

我目前正在从一个客户端接收请求的UDP服务器上工作。我收到的数据报是一个长度为5个字节的字节(char)数组,最后两个元素是一个端口号。从sockaddr_storage中提取IP地址和端口信息

最终,这个服务器将不得不返回它自己的数据报中的IP地址和端口号。

我已经知道如何使用inet_ntop和sockaddr结构,我已经连接并从打印出来的ip收到,但它返回的字符串不是我想要的格式。例如:

string1 = inet_ntop(their_addr.ss_family,get_in_addr(
    (struct sockaddr *)&their_addr),s, sizeof s); 

回报:

127.0.0.1 

或:

[1][2][7][.][0][.][0][.][1] 

,当我需要的东西,如:

[127][0][0][1] 

我应该使用某种性格和数组操作使我的4元素byt数组?或者一个sockaddr有这种信息的方式,我可以把它留在这个十六进制格式并返回它?

回答

12

假设为IPv4。

sockaddr_storagesockaddr结构的地址转换为IPv4版本sockaddr_in后,即可访问IPv4地址的单个字节。

struct sockaddr_in *sin = (struct sockaddr_in *)&their_addr; 

然后就可以采取s_addr构件这是一个32位值(in_addr_t)的地址保持的4个字节的IP地址(网络字节顺序),并将其转换为一个指向unsigned char其然后让您访问该值的单个字节。

unsigned char *ip = (unsigned char *)&sin->sin_addr.s_addr; 

printf("%d %d %d %d\n", ip[0], ip[1], ip[2], ip[3]); 
+0

这正是我一直在寻找。简洁而优秀。谢谢@Kludas – Ryanman

5

你想可能使用getnameinfo()功能:

int getnameinfo(const struct sockaddr *sa, socklen_t salen, 
        char *host, size_t hostlen, 
        char *serv, size_t servlen, int flags); 

例如为:

struct sockaddr_storage client_addr; 
socklen_t client_len = sizeof(struct sockaddr_storage); 

/* Accept client request */ 
int client_socket = accept(server_socket, 
    (struct sockaddr *)&client_addr, &client_len); 

char hoststr[NI_MAXHOST]; 
char portstr[NI_MAXSERV]; 

int rc = getnameinfo((struct sockaddr *)&client_addr, 
    client_len, hoststr, sizeof(hoststr), portstr, sizeof(portstr), 
    NI_NUMERICHOST | NI_NUMERICSERV); 

if (rc == 0) 
    printf("New connection from %s %s", hoststr, portstr);