[unix] 利用Unix系统函数进行网络编程(一)

1.客户端软件设计–基础篇

1.1标识服务器的位置
1.1.1依据域名得到二进制ip地址
int main()
{
    /*
     * 解析域名用gethostbyname()
     * hostent *gethostbyname (const char *__name);
     *
     *
     * hostent的结构
     * char *h_name;             正式名字 official name
     * char **h_aliases;         别名列表
     * int h_addrtype;           地址类型(ipv4/AF_INET或者ipv6/AF_INET6)
     * int h_length;             主机ip地址的长度
     * char **h_addr_list;       主机ip地址(以网络字节号序存储),若想打印需用inet_ntop()进行地址转换,
     *                           定义了h_addr为h_addr_list[0]
     *
     *
     * inet_ntop()地址转换
     * const char *inet_ntop (int __af, const void *__restrict __cp,char *__restrict __buf, socklen_t __len)
     * 参数说明:_af为地址类型,即h_addrtype参数,指明是ipv4还是ipv6
     *        _restrict_cp为一个以网络字节号存储的ip地址,给出ip
     *        __restrict __buf是一个char*的32(ipv4)地址,用于存放计算结果,此函数会返回此地址
     *        socklen_t_len是_restrict_buf的长度,用sizeof即可计算
     *
     * domainName为域名
     * hostent1为解析完域名后的结构体,存储了解析后的信息
     * str是用来存储2进制ip地址的
     */
    char *domainName, **pptr;
    struct hostent *hostent1;
    char str[32];

    domainName = "www.baidu.com";

    //域名解析出错
    if ((hostent1 = gethostbyname(domainName)) == NULL)
    {
        printf(" gethostbyname error for host:%s\n", domainName);
        return 0;
    }

    //解析正确
    printf("official hostname:%s\n", hostent1->h_name);//正式名字official name
    for (pptr = hostent1->h_aliases; *pptr != NULL; pptr++)
        printf(" alias:%s\n", *pptr);//别名

    switch (hostent1->h_addrtype)
    {
        case AF_INET:
        case AF_INET6:
            pptr = hostent1->h_addr_list;
            for (; *pptr != NULL; pptr++)
                printf(" address:%s\n", inet_ntop(hostent1->h_addrtype, *pptr, str, sizeof(str)));//点分十进制ip
            printf(" first address: %s\n", inet_ntop(hostent1->h_addrtype, hostent1->h_addr, str, sizeof(str)));//第一个ip
            break;
        default:
            printf("unknown address type\n");
            break;
    }

    return 0;

}
1.1.2依据名称(应用层协议)查找熟知端口号
void testGetservbyname()
{
    /*
     * getserverbyname()通过应用层与运输层协议名称获得熟知端口号
     * servent *getservbyname (const char *__name, const char *__proto);
     * _name代表应用层协议 _proto代表运输层协议
     *
     * servent结构体
     * char *s_name 应用层协议名称
     * char *s_proto 运输层协议名称
     * int s_port 端口号,需用ntohs进行转换----nthos将一个16位网络字节顺序转换为主机字节顺序
     * char **s_aliases 协议的别名
     */
    servent *se = NULL;
    int i = 0;

    se = getservbyname("ftp", "tcp");
    if (!se)
        return;

    printf("name : %s\n", se->s_name);
    printf("port : %d\n", ntohs(se->s_port));
    printf("proto : %s\n", se->s_proto);
    for (i = 0; se->s_aliases[i]; i++)
        printf("aliases : %s\n", se->s_aliases[i]);

}
1.1.3依据协议名称返回代表其的整数常量
void testGetprotobyname(){
    /*
     * getprotobyname()通过运输层协议名称获取 一个代表其的整数常量
     * protoent *getprotobyname (const char *__name);
     * name:运输层协议名称
     * 
     * protoent
     * char * p_name:运输层协议名称
     * char * **p_aliases:协议别名
     * int p_proto:整数常量
     */
    char *name="icmp";
    protoent *protoent1=getprotobyname(name);
    printf("%s\n",protoent1->p_name);
    printf("%d\n",protoent1->p_proto);
}

2.客户端实现–实战篇

2.1确定服务器地址,然后建立连接
//1.标志ip与端口号的结构体--sockaddr_in与sockaddr
struct sockaddr_in:
	struct in_addr sin_addr;/* ip地址*/
	int sin_port;/* 端口号*/
	sin_family;/* 协议族,取PF_INET即可*/
	
//其中ip地址/端口号可能需要自己通过域名/应用层协议获取
//获取ip地址--将域名映射为ip地址 sin_addr/将电分十进制ip转换为网络ip
struct hosten *phe;
phe=gethostbyname("www.baidu.com");
memcpy(&sin.sin_addr,phe->h_addr,phe->length);

sin.sin_addr.s_addr = inet_addr("192.168.0.1");

//获取端口号--将服务映射为端口 sin_port
struct servent *pse;
pse=getservbyname("http","tcp");
sin.sin_port=pse->s_port;

//2.创建套接字socket,连接
int socetfd=socket(PF_INET,SOCK_STREAM,0);
connect(socketfd,(struct sockaddr *)&sin,sizeof(sin))

//3.......
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值