基本知识

关于accept和getpeername的address_len参数的标题

#include <sys/socket.h>

一、gethostname,gethostbyname的用法

那三个函数能够用来获得主机的新闻。
gethostname:获取主机的名字
gethostbyname:通过名字获取其余的新闻(比如ip)

1.gethostname:
man手册里面包车型客车表达(部分):
       #include <unistd.h>
       int gethostname(char *name, size_t len);
       int sethostname(const char *name, size_t len);
DESCRIPTION
       These  system calls are used to access or to change the hostname
of the
       current processor.
RETURN VALUE
       On  success,  zero is returned.  On error, -1 is returned, and
errno is
       set appropriately.

2.gethostbyname:
       #include <netdb.h>
       extern int h_errno;
       struct hostent *gethostbyname(const char *name);

能够看来获取的从头到尾的经过保留在贰个指南针里面。上边大家来看那几个指针指向的内容:
       The hostent structure is defined in <netdb.h> as follows:
           struct hostent {
               char  *h_name;            /* official name of host
*/
               char **h_aliases;         /* alias list */
               int    h_addrtype;        /* host address type */
               int    h_length;          /* length of address */
               char **h_addr_list;       /* list of addresses */
           }
           #define h_addr h_addr_list[0] /* for backward
compatibility */
       The members of the hostent structure are:
       h_name The official name of the host.
       h_aliases
              An array of alternative names for the host, terminated by
a NULL
              pointer.
       h_addrtype
              The type of address; always AF_INET or AF_INET6 at
present.
       h_length
              The length of the address in bytes.
       h_addr_list
              An array of pointers to network addresses for the host
(in  net‐
              work byte order), terminated by a NULL pointer.
       h_addr The first address in h_addr_list for backward
compatibility.
下一场是再次来到值:
www.bifa365.com,未果重返空。不然再次来到值指向大家需求的音讯的可怜结构体。
RETURN VALUE
       The  gethostbyname()  and  gethostbyaddr() functions return the
hostent
       structure or a NULL pointer if an error occurs.  On error,
the  h_errno
       variable  holds  an  error number.  When non-NULL, the return value may
       point at static data, see the notes
below.

实例:

#include<stdio.h>
#include<unistd.h>
#include<netdb.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
int main()
{

    printf("%s() +++ hello\n", __func__);
    char host[256] = {0};
    if(gethostname(host, sizeof(host)) < 0)
    {
        perror("gethostname");
        return -1;
    }    

    printf("host:%s\n", host);
    struct hostent *myhost = NULL;
    if(!(myhost = gethostbyname(host)))
    {
        perror("gethostbyname");
           return -2;
    }
    int i = 0;
    while(myhost && myhost->h_addr_list[i])
    {
        printf("ip%d:%s\n", i+1, inet_ntoa(*(struct in_addr*)myhost->h_addr_list[i]));
        i++;    
    }
    return 0;
}

运行:

xcy@xcy-virtual-machine:~/test/gethost$ ./a.out 
main() +++ hello
host:xcy-virtual-machine
ip1:127.0.1.1

 

 

 

int bind(int socket,const struct sockaddr *addr,socklen_t len);

二、关于getsockname和getpeername

1.getsockname:获取一个套接字的名字。获取本地的地址和端口消息。
#include <sys/socket.h>
int getsockname(int sockfd, struct sockaddr *addr, socklen_t
*addrlen);
未果再次来到-1,成功重回0。addr是输入参数,addrlen是输入输出参数

2.getpeername:获取socket的对方的地方
#include <sys/socket.h>
int getpeername(int sockfd, struct sockaddr *addr, socklen_t
*addrlen);
倒闭重回-1,成功重临0。addr是输入参数,addrlen是输入输出参数

注意:
1)对于server来说:
bind以后就能够调用getsockname来获得本地地址和端口了,只不过尔尔没啥意思,因为正是投机绑定的。
只有在accept现在(便是有连接之后才)手艺用getpeername获取client的ip和端口。(client的ip和port也足以在accept函数的第4个参数中带出)
2)对于client来说:
创建socket并不会分配ip和端口。用getsockname获抽出来的数目全都以0.
在接二连三(connect)之后才足以用getsockname获取本人的ip和端口。也足以用getpeername获取服务器的。

3.怎么运用:伪代码
客商端代码:

......
    if(connect(sockfd, (struct sockaddr*)&addr, sizeof(addr)) < 0)
    {
        perror("connect");
        return -2;
    }
// 在连接以后才能获取
    struct sockaddr_in addr2;
    socklen_t len = sizeof(addr2); // 
    //if(getsockname(sockfd, (struct sockaddr*)&addr2, &len) < 0) // 这个是获取自己的ip和端口
    if(getpeername(sockfd, (struct sockaddr*)&addr2, &len) < 0)  // 这个是获取连接方的
    {
        perror("getsockname");
        return -3;
    }
printf("Get: port:%d, ip:%s\n", ntohs(addr2.sin_port), inet_ntoa(addr2.sin_addr));
......

服务端代码:

。。。// 前面有bind,listen等动作,这里只处理连接的
    while(1)
    {    
        int conn = accept(listenfd, (struct sockaddr*)&connaddr, &len);
        if(conn < 0)
        {
            perror("accept");
            return -4;
        }
          // 这里的connaddr就跟下面getpeername获取的一样
        char strip[64] = {0};
        char *ip = inet_ntoa(connaddr.sin_addr);
        strcpy(strip, ip);
        printf("new client connect,ip:%s, port:%d\n", strip,ntohs(connaddr.sin_port));
        struct sockaddr_in addr2;
        socklen_t len = sizeof(addr2);
    //    if(getsockname(conn, (struct sockaddr*)&addr2, &len) < 0) // 这个是获取自己的ip和端口
        if(getpeername(conn, (struct sockaddr*)&addr2, &len) < 0) // 这个是获取连接方的。这样其实跟accept参数带出来的数据是一样的
        {
            perror("getsockname");
            return -3;
        }
        printf("get: port:%d, ip:%s\n", ntohs(addr2.sin_port), inet_ntoa(addr2.sin_addr));        
        deal_connect(conn); // 用来处理连接的函数
    }
。。。。。。

 

socket编程中,难免会有亟待获得对端音讯的时候

int getsockname(int sockfd,struct sockaddr *restrict addr,socklen_t
*restrict alenp);

  www.2cto.com  

开掘绑定到八个套接字的地址

socket本人给我们提供了三个艺术,accept()和getpeername()

 

 

要是套接字已经很对方一而再,能够用getpeername找到对方地址

accept()

int getperrname(int sockfd,struct sockaddr *restrict addr,socklen_t
*restrict alenp);

 

 

int accept(int socket, struct sockaddr *restrict address, socklen_t
*restrict address_len);

确立连接:

socket:这里的socket是由此bind绑定地址过的socket,能够精通为劳动器端的socket。以前有二个监听(listen)操作,accept算是它的接二连三操作,它们的操作对象皆以同多个socket。

int connect(int sockfd,const struct sockaddr *addr,socklen_t len);

  www.2cto.com  

 

restrict address:这里的地方变量,用于保存对端的地点音信。

int listen(int sockfd,int backlog);

 

 

address_len:参数二restrict address的尺寸,在写入restrict
address音讯时,也会将写入消息的长短保存到此变量。注意:manpage里对这一个参数有贰个证实,在行使前务须求初步化,前边继续注明。

int accept(int sockfd,struct sockaddr *restrict addr,socklen_t
*restrict len);

 

再次来到值:成功会回来对端的socket
fd(非负),退步的话会回去-1.(此时赢得errno,errmsg是二个好习于旧贯)

 

getpeername()

 

 

 

int getpeername(int sockfd, struct sockaddr *addr, socklen_t
*addrlen);

 

 

socket:这里的socket和accept中对应的socket有所不一样,它应有是对端的socket。

 

restrict address:同上

 

address_len:同上

 

那中间关于address_len还关乎到一个标题,笔者就犯过那几个张冠李戴:使用前,未有早先化。

 

周到看看manpage,关于这么些参数的,事实是这么的:

 

以accept为例,当accept收到了client的连天,会做两件事:

 

1,以address_len的值来写对端消息到restrict
address,比方,address_len为1,那么对端的音讯,只写1个字节到restrict
address(也许因为新闻长度为XX,大于1而根本就不写进去,这些可能更加大,有待考证)

 

2,实际上收到的对端的消息长度写到address_len

 

因此当您的address_len那么些变量未有伊始化的时候,其默许值为1(Fedora-16),无法把音信完全写入restrict
address,产生没有获得到对端音信的假象。

 

socket编制程序中,难免会有需求获得对端消息的时候 www.2cto.com
socket本人给我们提供了四个情势,ac…

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*
*
Website