码迷,mamicode.com
首页 > 其他好文 > 详细

关于getsockname()/getpeername()函数第一次被调用得到0.0.0.0结果的说明

时间:2017-03-14 00:16:09      阅读:330      评论:0      收藏:0      [点我收藏+]

标签:ges   []   string   exp   lock   blocks   display   简单   tar   

最近阅读UNIX网络编程第四章时,书本末尾介绍了两个函数getsockname()和getpeername(),可以用于获取服务器端和客户端的IP地址与端口,原本很简单的两个函数,过一眼即明白函数的用法,但在实际编程测试中,却出现了一个让人意外的结果,这两个函数在第一个客户连接时解析出的IP地址和端口全部为0,出乎我的期望。而在后面的客户连接时,打印出的IP地址和端口却是正确的。

下面先给出客户端和服务端的代码:

客户端:

技术分享
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
#include <pton32>
#include <iostream>


int main(int argc, char const *argv[])
{
    int         sockfd;
    sockaddr_in srvaddr;

    bzero(&srvaddr, sizeof(srvaddr));
    srvaddr.sin_family = AF_INET;
    if (argc < 2)
    {
        std::cout << "usage:" << argv[0] << " <IP address>" << std::endl;
        return -1;
    }
    srvaddr.sin_addr = pton32(argv[1]);
    srvaddr.sin_port = htons(7777);

    sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    if (connect(sockfd, (sockaddr *)&srvaddr, sizeof(srvaddr)) != 0)
    {
        std::cout << "connect error,retry please.";
        throw;
    }

    char str[128] = {\0};
    while ((read(sockfd, str, 127)) > 0)
    {
        std::cout << str <<  ;
    }

    std::cout << std::endl;

    close(sockfd);

    return 0;
}
View Code

 

服务端:

技术分享
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
#include <pton32>
#include <iostream>


int main(int argc, char const *argv[])
{
    int             listenfd, connfd;
    sockaddr_in     cliaddr, srvaddr;

    bzero(&srvaddr, sizeof(srvaddr));
    srvaddr.sin_family              = AF_INET;
    srvaddr.sin_addr.s_addr         = htonl(INADDR_ANY);
    srvaddr.sin_port                = htons(7777);

    listenfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (bind(listenfd, (sockaddr *)&srvaddr, sizeof(srvaddr)))
    {
        std::cout << "bind failed." << std::endl;
        return -1;
    }

    if (listen(listenfd, 32))
    {
        std::cout << "listen failed." << std::endl;
        return -1;
    }

    char str[128] = {\0};

    bzero(&cliaddr, sizeof(cliaddr));

    while (true)
    {
        socklen_t length        = sizeof(cliaddr);
        connfd = accept(listenfd, (sockaddr *)&cliaddr, &length);

        sockaddr_in     local,          peer;
        socklen_t       local_len,      peer_len;
        bzero(&local, sizeof(local));
        bzero(&peer, sizeof(srvaddr));

        getsockname(connfd, (sockaddr *)&local, &local_len);
        getpeername(connfd, (sockaddr *)&peer,  &peer_len);

        char buff_local[64] = {\0}, buff_peer[64]  = {\0};

        if (inet_ntop(AF_INET, (void *)&local.sin_addr, buff_local, 63))
        {
            std::cout << buff_local << std::endl;
        }

        if (inet_ntop(AF_INET, (void *)&peer.sin_addr, buff_peer, 63))
        {
            std::cout << buff_peer << std::endl;
        }

        write(connfd, str, 127);
        close(connfd);
    }
    return 0;
}
View Code

 

其中的pton32头文件是我个人自定义的头文件,用于转换IP地址,定义如下:

技术分享
#include <netinet/in.h>
#include <arpa/inet.h>
#include <strings.h>
#include <iostream>


in_addr pton32(const char *str)
{
        in_addr s_addr;
        try
        {
                if (1 == inet_pton(AF_INET, str, &s_addr))
                        return s_addr;
                else
                        throw false;
        }
        catch (bool b)
        {
                std::cout << "convert failed." << std::endl;
        }

        bzero(&s_addr, sizeof(s_addr));
        return s_addr;
}
View Code

 

 

关于getsockname()/getpeername()函数第一次被调用得到0.0.0.0结果的说明

标签:ges   []   string   exp   lock   blocks   display   简单   tar   

原文地址:http://www.cnblogs.com/pluse/p/6545514.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!