2012-10-10 303 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);