您好我创建了一个函数,它接受一个接受的sockFD作为输入,并将表示形式的IP地址输出到一个字符串。该函数似乎工作正常,直到我通过inet_ntop的调用打包字符串,它返回一个空指针,从而给我我的错误。错误显示为设备上没有剩余空间我不明白,因为我有足够的ram和rom。无论如何,下面是我正在使用的功能。
void getTheirIp(int s, char *ipstr){ // int s is the incoming socketFD, ipstr points the the calling
// functions pointer.
socklen_t len;
struct sockaddr_storage addr;
len = sizeof(addr); //I want to store my address in addr which is sockaddr_storage type
int stat;
stat = getpeername(s, (struct sockaddr*)&addr, &len); // This stores addrinfo in addr
printf("getTheirIP:the value of getpeername %d\n",stat);
// deal with both IPv4 and IPv6:
if ((stat=addr.ss_family) == AF_INET) { // I get the size of the sock first
printf("getTheirIP:the value of addr.ss_family is %d\n",stat);
ipstr = malloc(INET_ADDRSTRLEN); // I allocate memory to store the string
struct sockaddr_in *s = (struct sockaddr_in *)&addr; // I then create the struct sockaddr_in which
// is large enough to hold my address
if(NULL == inet_ntop(AF_INET, &s->sin_addr, ipstr, sizeof(ipstr))){ // I then use inet_ntop to
printf("getTheirIP:the value of inet_ntop is null\n");// retrieve the ip address and store
perror("The problem was"); // at location ipstr
}
} else { // AF_INET6 this is the same as the above except it deals with IPv6 length
ipstr = malloc(INET6_ADDRSTRLEN);
struct sockaddr_in6 *s = (struct sockaddr_in6 *)&addr;
inet_ntop(AF_INET6, &s->sin6_addr, ipstr, sizeof(ipstr));
}
printf("%s",ipstr);
}
我遗漏了程序的其余部分,因为它太大而不适合我只想专注于修复这部分。但是,下面我将向您展示调用此函数的main()的一部分。
newSock = accept(listenSock,(struct sockaddr *)&their_addr,&addr_size);
char *someString;
getTheirIp(newSock,someString);
任何帮助都会很棒。谢谢!
答案 0 :(得分:7)
inet_ntop(AF_INET, &s->sin_addr, ipstr, sizeof(ipstr))
sizeof
是错误的,因为ipstr
是一个指针(它会产生指针的大小,类似于4
或8
)。您需要传递ipstr
缓冲区的可用长度。
答案 1 :(得分:4)
如联机帮助页中所述,从inet_ntop获取ENOSPC意味着:
转换后的地址字符串将超过size指定的大小。
您将sizeof(ipstr)作为size参数,即char指针 ipstr 所占的存储量。你需要传递缓冲区的大小。
答案 2 :(得分:1)
对于初学者,我会改为使用双指针:
void getTheirIp(int s, char **ipstr_pp)
下一步 - 这是错误的:ipstr是一个4字节指针:
inet_ntop(AF_INET, &s->sin_addr, ipstr, sizeof(ipstr)
我认为你想要“INET_ADDRSTRLEN”。
最后,我鼓励你打印出实际的错误#。或者至少剪切/粘贴完整的perror()文本(我认为应该包含错误#)。