C 如何获取用于连接到我的服务器的IP地址?

C 如何获取用于连接到我的服务器的IP地址?,c,sockets,network-programming,ip-address,C,Sockets,Network Programming,Ip Address,我有一台服务器在多个设备(LAN、WiFi,可能还有一些VPN)上监听 监听绑定一个套接字(AF_INET)绑定所有接口上要公开的任何接口 然后,客户端连接并启动交换 在这一点上,我怎样才能获得关于哪个设备用于连接的信息 等价地:如何获取用于连接的客户端的IP地址 编辑: 根据@Barmar的建议,我尝试了以下方法: #include <sys/socket.h> #include <netinet/ip.h> #include <sys/un.h> #inc

我有一台服务器在多个设备(LAN、WiFi,可能还有一些VPN)上监听

监听绑定一个套接字(AF_INET)绑定所有接口上要公开的任何接口

然后,客户端连接并启动交换

在这一点上,我怎样才能获得关于哪个设备用于连接的信息

等价地:如何获取用于连接的客户端的IP地址

编辑: 根据@Barmar的建议,我尝试了以下方法:

#include <sys/socket.h>
#include <netinet/ip.h>
#include <sys/un.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define handle_error(msg) \
        do { perror(msg); exit(EXIT_FAILURE); } while (0)

void error(char *msg)
{
    perror(msg);
    exit(1);
}

int main(int argc, char *argv[])
{
    int sockfd, newsockfd, portno;
    unsigned clilen;
    struct sockaddr_in serv_addr, cli_addr;
    struct sockaddr_in myaddr;
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
        error("ERROR creating socket");
    bzero((char *) &serv_addr, sizeof(serv_addr));
    portno = 5666;
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    serv_addr.sin_port = htons(portno);
    if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
        error("ERROR on binding");
    listen(sockfd, 5);
    clilen = sizeof(cli_addr);
    newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
    if (newsockfd < 0)
        error("ERROR on accept");

    clilen = sizeof(myaddr);
    if (getsockname(newsockfd, (struct sockaddr *)&myaddr, &clilen))
        error("ERROR in getsockname");

    unsigned int i = myaddr.sin_addr.s_addr;
    int p = myaddr.sin_port;
    int a = i & 0xff;
    i >>= 8;
    int b = i & 0xff;
    i >>= 8;
    int c = i & 0xff;
    i >>= 8;
    int d = i & 0xff;
    printf("my address is: %d.%d.%d.%d:%d\n", a, b,c, d, p);

    return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#定义句柄错误(msg)\
do{perror(msg);exit(exit_FAILURE);}while(0)
无效错误(字符*消息)
{
佩罗尔(味精);
出口(1);
}
int main(int argc,char*argv[])
{
int sockfd、newsockfd、端口号;
未签名的clilen;
服务地址中的结构sockaddr\u,cli\u addr;
myaddr中的结构sockaddr_;
sockfd=套接字(AF_INET,SOCK_STREAM,0);
if(sockfd<0)
错误(“创建套接字时出错”);
bzero((char*)&serv_addr,sizeof(serv_addr));
端口号=5666;
serv_addr.sin_family=AF_INET;
serv_addr.sin_addr.s_addr=INADDR_ANY;
serv_addr.sin_port=htons(端口号);
if(bind(sockfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr))<0)
错误(“绑定错误”);
听(sockfd,5);
clilen=sizeof(cli_addr);
newsockfd=accept(sockfd,(struct sockaddr*)&cli\u addr,&clilen);
if(newsockfd<0)
错误(“接受错误”);
clilen=sizeof(myaddr);
if(getsockname(newsockfd,(struct sockaddr*)&myaddr,&clilen))
错误(“getsockname中的错误”);
无符号整数i=myaddr.sin\u addr.s\u addr;
int p=myaddr.sinu端口;
int a=i&0xff;
i>>=8;
intb=i&0xff;
i>>=8;
int c=i&0xff;
i>>=8;
int d=i&0xff;
printf(“我的地址是:%d.%d.%d.%d:%d\n”,a、b、c、d、p);
返回0;
}
。。。(经过一点调试)它可以工作


请注意,端口不是预期的值(5666),而是一致的8726。

如果您使用的是
SOCK_流
socket(即TCP),而不是
SOCK_DGRAM
(即UDP),请调用
accept()
返回的套接字

如果您使用的是一个数据报套接字,我认为没有一种可移植的方法可以使用单个套接字来实现。传统的解决方案是为每个本地地址绑定一个单独的套接字,而不是使用
INADDR\u ANY
,然后使用
epoll()
select()
等待所有本地地址上的消息。您可以根据接收消息的套接字来判断它们连接到的地址


Linux和Windows有一个扩展,通过在套接字上设置
IP\u PKTINFO
选项并使用
recvmsg()
接收数据包,您可以更轻松地执行此操作。在
msgheader.msg_控件中
可以获得数据包的目标地址。请参见

参数addr是指向sockaddr结构的指针。此结构由对等套接字的地址填写
我想他想要的是他们连接到的本地地址,而不是客户的地址。我可以确认@Barmar解释。我尝试按照您的建议,但我总是得到INADDR_ANY(0.0.0.0)地址(请参阅我对问题的编辑).你应该在
newsockfd
上调用它,而不是
sockfd
。当然,我的错!答案被接受。你能解释一下为什么端口号总是8726(而不是预期的5666)吗?这在
newsocket
中也会发生。您知道在分配到
sin\u端口时必须如何调用
htons()
?读取时需要调用
ntohs()
,以反转进程。5666是0x1622,8726是0x2216——注意关系吗?