Visual Studio 控制台编程getXbyY()

Visual Studio 控制台编程getXbyY()

实验目的

掌握Visual Studio控制台应用编程的基本方法

掌握Windows Sockets DLL的初始化和释放方法

掌握Windows Sockets API调用的一般步骤

使用Windows Sockets的API函数获得指定机器的信息

(包括主机名、服务名、协议、IP地址)

实验过程

实现 gethostbyname()函数

此函数含义为通过IP地址或网址输出相应主机的信息

实验环境:Visual Studio 2019

创建win32控制台应用程序项目

如图:

新建项目 -> Windows桌面向导 -> 创建 -> 控制台应用程序

BwtGC9.png

创建出win32控制台应用程序

注:在vs2019中创建好此项目后不用再在代码中编写#include “stdafx.h”头文件,vs2019在项目中自带了此头文件,因此不用再次编写。

对项目属性进行一些修改:

修改字符集为多字节字符集(未修改可能导致IP地址等参数无法相匹配)

修改嵌入清单为否(在VS2010中不设置将编译错误)

命令参数中填入想获得信息的网址(以百度为例)

源代码

// gethostbyname.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <windows.h>
#pragma comment(lib, "ws2_32.lib") //连接静态库

int main(int argc, char** argv)
{

    //-----------------------------------------
    // Declare and initialize variables
    WSADATA wsaData;
    int iResult;

    DWORD dwError;
    int i = 0;

    struct hostent* remoteHost;//定义host entry结构体指针变量,定义见课件。
    char* host_name;
    struct in_addr addr; //以各种形式存放4个字节的IPv4地址

    char** pAlias; //定义别名列表指针变量

    // Validate the parameters
    if (argc != 2) {           //为何argc要等于2?,程序运行时每个参数分别是什么?
        printf("usage: GetHostIP hostname\n"); //提示程序运行时需要输入主机名作为参数
        return 1;
    }
    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);//与操作系统确认支持的WinSock版本
    if (iResult != 0) {
        printf("WSAStartup failed: %d\n", iResult);
        return 1;
    }

    host_name = argv[1]; //提取用户输入的主机名
    
    printf("Calling gethostbyname with %s\n", host_name);
    remoteHost = gethostbyname(host_name);
    if (remoteHost == NULL) {  //报错,返回。
        dwError = WSAGetLastError();
        if (dwError != 0) {
            if (dwError == WSAHOST_NOT_FOUND) {
                printf("Host not found\n");
                return 1;
            }
            else if (dwError == WSANO_DATA) {
                printf("No data record found\n");
                return 1;
            }
            else {
                printf("Function failed with error: %ld\n", dwError);
                return 1;
            }
        }
    }
    else {  //依次显示获取的主机名称、多个别名、地址类型、地址长度、地址列表
        printf("Function returned:\n");
        printf("\tOfficial name: %s\n", remoteHost->h_name);//显示主机名称
        for (pAlias = remoteHost->h_aliases; *pAlias != 0; pAlias++) { //循环显示别名
            printf("\tAlternate name #%d: %s\n", ++i, *pAlias);
        }
        printf("\tAddress type: ");
        switch (remoteHost->h_addrtype) {
        case AF_INET:
            printf("AF_INET\n"); //显示地址类型
            break;
        case AF_NETBIOS:
            printf("AF_NETBIOS\n");
            break;
        default:
            printf(" %d\n", remoteHost->h_addrtype);
            break;
        }
        printf("\tAddress length: %d\n", remoteHost->h_length);//显示地址长度

        i = 0;
        if (remoteHost->h_addrtype == AF_INET)
        {
            while (remoteHost->h_addr_list[i] != 0) {  //循环显示主机地址
                addr.s_addr = *(u_long*)remoteHost->h_addr_list[i++];
                printf("\tIP Address #%d: %s\n", i, inet_ntoa(addr));//将地址转换成点分十进制显示。
            }
        }
        else if (remoteHost->h_addrtype == AF_NETBIOS)
        {
            printf("NETBIOS address was returned\n");
        }
    }

    iResult = WSACleanup();
    if (iResult != 0) {
        printf("WSACleanup failed: %d\n", iResult);
        return 1;
    }

    return 0;
}

运行结果:

代码分析

首先对WSAStartup()进行初始化

WSAStartup()函数声明如下

int WSAStartup ( WORD wVersionRequested, LPWSADATA lpWSAData );

其中WORD wVersionRequested 为socket版本,LPWSADATA lpWSAData 为相应WSAData变量,返回一个整数反应是否成功初始化。

Gethostbyname()函数原型为

struct hostent FAR * PASCAL FAR gethostbyname(const char FAR * name);

通过一个网站名返回此主机信息,主机信息存放在hostent结构体中,该函数调用DNS系统来获取对应域名或主机名的相关信息。

hostent结构体定义如下:

struct hostent{
char * h_name;
char ** h_aliases;
short h_addrtype;
short h_length;
char ** h_addr_list;
#define h_addr h_addr_list[0];
};

其中包含数据主机名、别名列表、地址类型、地址长度、地址列表

如果通过gethostbyname()函数得到的数据异常,则获取网站名失败,读取WSAGetLastError();函数得到错误原因代码赋值给dwError,有三种错误情况。通过dwError所得到的错误代码输出错误原因:主机未找到/无数据记录/函数错误以及代码

如果通过gethostbyname()函数得到的数据正常,则正常得到数据。由不同主机返回不同信息如地址类型等。

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值