名称 | 值 |
---|---|
操作系统 | Windows 11 家庭中文版22H2 |
内存 | 16GB |
CPU | Intel® Core™ i7-8750H CPU @ 2.20GHz 2.20 GHz |
IDE | DEV-C++ 5.10 |
需要注意的是引用winsock2.h头文件后,还需要链接该头文件的实现文件,在本机上使用宏#pragma comment (lib, “ws2_32.lib”)无法成功添加该实现文件ws2_32。手动编译时会出现如下报错信息:
参考网上许多解决办法没有效果,最后解决办法如下:
如下图,可以打开DEV-C++菜单栏的Toos->Compiler Options-> General,找到Add the following commands when calling the compiler:勾上复选框,在下面的输入框中写入-lwsock32
并确定。这样编译运行的时候就可以自动链接了。
这样做相当于编译命令变成了gcc socket_exp.c -o socket_exp.exe -lwsock32
,其中socket_exp是我的文件名。举一反三,在VSCode中就可以自己手动链接了。
使用IDE新建一个C语言程序进行编写。代码如下:
#include
#include
void queryLocalIP() {
WSADATA data;
if(WSAStartup(MAKEWORD(1,1),&data)!=0){
printf("初始化错误");
}
char host[255]="";
if(gethostname(host,sizeof(host))==SOCKET_ERROR){
printf("无法获取计算机主机名\n");
}
else{
printf("本机名称为:%s\n",host);
}
struct hostent *p=gethostbyname(host);
if(p==0){
printf("无法获取计算机主机名及IP\n");
}
else{
//本机IP:循环输出本机所有网卡的IP,其中包括虚拟网卡
int i;
for(i=0;p->h_addr_list[i]!=0;i++){
struct in_addr in;
memcpy(&in,p->h_addr_list[i],sizeof(struct in_addr));
printf("本机的第%d块网卡的IP为:%s\n",i+1,inet_ntoa(in));
//cout<<"第"<
}
}
WSACleanup();
}
void queryHostNameIP(char *host) {
WSADATA data;
if(WSAStartup(MAKEWORD(1,1),&data)!=0){
printf("初始化错误");
}
//char host[255];
struct hostent *p=gethostbyname(host);
if(p==0){
printf("无法获取%s的信息\n",host);
}
else{
//本机IP:循环输出本机所有网卡的IP,其中包括虚拟网卡
int i;
for(i=0;p->h_addr_list[i]!=0;i++){
struct in_addr in;
memcpy(&in,p->h_addr_list[i],sizeof(struct in_addr));
printf("解析%s的第%d个IP为:%s\n",host,i+1,inet_ntoa(in));
//cout<<"第"<
}
}
WSACleanup();
}
int main(){
queryLocalIP();
printf("=================================\n");
char* hostname = "www.baidu.com";
queryHostNameIP(hostname);
printf("=================================\n");
//输出个人信息
printf("Ranly 2022/4/23");
return 0;
}
ok,下面编译运行就正常了。用完以后记得把编译设置里加上去的参数去掉,以便以后写其他代码出问题。
int gethostname(char *name, size_t len);
参数说明:
参数 | 类型 | 说明 |
---|---|---|
name | char * | 用于存储获得的主机名,其长度必须为len字节或是更长。 |
len | size_t | 接收缓冲区的最大长度,可通过sizeof(name)获取。 |
返回值:
struct hostent *gethostbyname(const char *hostname);
参数说明:
参数 | 类型 | 说明 |
---|---|---|
hostname | const char * | 要查询的主机名,域名 |
返回值:
对于一个hostname,可以通过gethostbyname(char *hostname);
方法来获得一个hostent的结构体的指针。
传入的hostname可以是通过gethostname获取的本机主机名或是本地局域网内可被发现的其它主机的名字,例如 LBW's PC
,也可以是一个常见的网络域名,例如某度的二级域名 www.baidu.com
。
struct hostent {
char *h_name; /* 主机的官方域名 */
char **h_aliases; /* 一个以NULL结尾的主机别名数组 */
int h_addrtype; /* 返回的地址类型,在Internet环境下为AF-INET */
int h_length; /* 地址的字节长度 */
char **h_addr_list; /* 一个以0结尾的二维数组,包含该主机的所有地址*/
};
详细解析:
struct sockaddr_in {
short int sin_family; /* 协议族 */
unsigned short int sin_port; /* 端口号 */
struct in_addr sin_addr; /* Internet 地址 */
unsigned char sin_zero[8]; /* 和结构体 sockaddr 大小相同 */
};
这个结构体就是32位的IP地址了。要进行格式化输出字符串,不要直接读取,而是使用char *inet_ntoa (struct in_addr);
方法将in_addr类型的变量转换为char数组,从而可以pirntf为用.
间隔的IP地址字符串。
struct in_addr {
union {
struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
struct { u_short s_w1,s_w2; } S_un_w;
u_long S_addr;
} S_un;
https://blog.csdn.net/k916631305/article/details/109498205
https://blog.csdn.net/u011608357/article/details/18862853
https://baike.baidu.com/item/inet_ntoa%28%29/10082005
https://www.cnblogs.com/kex1n/p/5524644.html
http://c.biancheng.net/view/2357.html
博客首发:https://ranlychan.top/archives/476.html