如果在服务器套接字的不同位置调用getpeername()和getsockname()会发生什么情况?

时间:2018-10-14 19:54:08

标签: c sockets

在带有套接字程序的C中,我试图在 server 套接字中插入getpeername()和getsockname,以在服务器端打印服务器套接字和客户端套接字的IP地址。注意:我的服务器套接字使用INADDR_ANY。我把getpeername()和getsockname()放在不同的位置:

1 / bind()之前:客户端和服务器套接字的IP地址均为0.0.0.0

2 / bind()之后:同样,客户端和服务器套接字的IP地址均为0.0.0.0

3 / accept()之后:客户端的IP地址为10.0.2.15,而服务器套接字仍为0.0.0.0

他们正确吗?在这种情况下,您能否解释为什么我得到0.0.0.0而不是特定地址?

注意:在我看来,我应该在bind()之后获得服务器套接字的特定IP地址,因为bind()已经将服务器套接字绑定到特定的IP地址。对于accept()之后,我认为客户端套接字和服务器套接字也应该是特定的IP地址,而不是0.0.0.0

1 个答案:

答案 0 :(得分:0)

我无法重现您的问题;例如考虑

[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
    private readonly ApplicationDbContext _appDbContext;

    private readonly UserManager<IdentityUser> _userManager;

    public ValuesController(UserManager<IdentityUser> userManager, ApplicationDbContext appDbContext)
    {
        _userManager = userManager;
        _appDbContext = appDbContext;
    }

    [HttpPost]
    public async Task<IActionResult> Post()
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        AppUser user = new AppUser();
        user.Email = "email@mail.co.uk";
        user.FirstName = "mark";
        user.LastName = "Macneill";
        user.UserName = "Saints22";
        await _userManager.CreateAsync(user, "P4$$word");

        return new OkObjectResult("Account created");

    }

    [HttpGet]
    public ActionResult<IEnumerable<string>> Get()
    {
        return new string[] { "value1", "value2" };
    }
}

通过#include <unistd.h> #include <netinet/ip.h> #include <sys/socket.h> int main(void) { struct sockaddr_in addr = { .sin_family = AF_INET, .sin_port = 0, .sin_addr = { INADDR_ANY }, }; int fd; int c_fd; struct sockaddr_in p_addr; socklen_t a_len = sizeof p_addr; fd = socket(AF_INET, SOCK_STREAM, 0); bind(fd, (void const *)&addr, sizeof addr); getpeername(fd, (void *)&p_addr, &a_len); getsockname(fd, (void *)&p_addr, &a_len); listen(fd, 10); c_fd = accept(fd, NULL, NULL); getpeername(c_fd, (void *)&p_addr, &a_len); getsockname(c_fd, (void *)&p_addr, &a_len); } 运行它并连接到绑定地址,显示

strace

在您的情况1 + 2中,没有服务器,$ strace ./a.out socket(AF_INET, SOCK_STREAM, IPPROTO_IP) = 3 bind(3, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("0.0.0.0")}, 16) = 0 getpeername(3, 0x7ffdcf3af130, [16]) = -1 ENOTCONN (Transport endpoint is not connected) getsockname(3, {sa_family=AF_INET, sin_port=htons(60093), sin_addr=inet_addr("0.0.0.0")}, [16]) = 0 listen(3, 10) = 0 accept(3, NULL, NULL) = 4 getpeername(4, {sa_family=AF_INET, sin_port=htons(35048), sin_addr=inet_addr("127.0.0.1")}, [16]) = 0 getsockname(4, {sa_family=AF_INET, sin_port=htons(60093), sin_addr=inet_addr("127.0.0.1")}, [16]) = 0 将失败,并显示getpeername()

ENOTCONN之前,accept()返回getsockname,因为您正在听0.0.0.0

但是在INADDR_ANY之后,accept() 返回本地地址。