windows网络编程 Visual Studio 控制台编程 getservbyport()

【实验目的】
掌握Visual Studio控制台应用编程的基本方法
掌握Windows Sockets DLL的初始化和释放方法
掌握Windows Sockets API调用的一般步骤
使用Windows Sockets的API函数获得指定机器的信息
(包括主机名、服务名、IP地址)

Winsocket代码:

#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结构体指针变量,定义见书p48。
	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);
	//获取主机的信息存放在hostent结构体中。该函数调用DNS系统来获取对应域名或主机名的相关信息,可以通过Wireshark抓包来进行验证。

		//对返回结果进行判断
	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();//与操作系统确认支持的WinSock版本
	if (iResult != 0) {
		printf("WSACleanup failed: %d\n", iResult);
		return 1;
	}

	return 0;
}

更改命令行参数:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
执行结果:
在这里插入图片描述
通过调用接口函数getservbyport()获取结构体信息struct servent*
代码展示:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>		// 此头文件放在<winsock2.h>或<ws2tcpip.h>之后
#pragma comment(lib, "ws2_32.lib") //连接静态库


int main(int argc, char** argv)
{
	WSADATA wsaData;		// 创建WSADATA的对象,存放socket版本号等信息
	int iResult;			// 接收WSAStarup()函数的返回值

	struct servent* remoteServ;

	/* -------------------------*/
	// 注册套接字
	iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);//与操作系统确认支持的WinSock版本
	if (iResult != 0) {
		printf("WSAStartup failed: %d\n", iResult);
		return 1;
	}


	short num = 1;

	printf("打印端口服务内容:\n");
	while (num < (unsigned short)-1)	// 65535
	{
		remoteServ = getservbyport(htons((u_short)num), "tcp");	// 服务端口,按网络字节顺序排列
		if (NULL == remoteServ);// printf("error %d ,please continue.\n", num);
		else {
			printf("服务名: %s \n", remoteServ->s_name);
			printf("端口号: %d \n", ntohs((u_short)remoteServ->s_port));	//端口号按网络字节顺序返回
			printf("协议名: %s \n\n", remoteServ->s_proto);
		}
		num++;
	}

	/* -------------------------*/
	// 释放资源
	iResult = WSACleanup();
	if (iResult != 0) {
		printf("WSACleanup failed: %d\n", iResult);
		return 1;
	}

	return 0;
}

执行结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值