Windows API 教程(九) 网络编程
茵蒂克丝
基础概念
IP 地址
IP 是英文 Internet Protocol (网络之间互连的协议)的缩写,也就是为计算机网络相互连接进行通信而设计的协议。任一系统,只要遵守 IP协议就可以与因特网互连互通。
所谓IP地址就是给每个遵循tcp/ip协议连接在Internet上的主机分配的一个32bit地址。按照TCP/IP协议规定,IP地址用二进制来表示,每个IP地址长32bit,比特换算成字节,就是4个字节。为了方便人们的使用,IP地址经常被写成十进制的形式,中间使用符号 “.” 分开不同的字节,如:192.168.1.1。在因特网中,主机的标识便是它ip地址。
常见的获取服务器ip的方法是使用系统自带的ping命令。例,打开cmd输入:
ping www.baidu.com
输出:
其中的 115.239.210.27 就是baidu服务器的地址了
服务端与客户端
服务端与客户端在计算机的世界里,凡是提供服务的一方我们称为服务端(Server),而接受服务的另一方我们称作客户端(Client)。
网站提供网页数据的服务,使用者接受网站所提供的数据服务,所以使用者在这里就是客户端,响应使用者要求的网站即称为服务端。
不过客户端及服务端的关系不见得一定建立在两台分开的机器上,同一台机器中也有这种主从关系的存在,提供服务的服务端及接受服务的客户端也有可能都在同一台机器上。
例如我们在提供网页的服务器上执行浏览器浏览本机所提供的网页,这样在同一台机器上就同时扮演服务端及客户端。
Socket
socket的英文原义是“孔”或“插座”。作为4BDS UNIX的进程通信机制,取后一种意思。通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄。
Scoket程勋分为服务端与客户端,服务端程序监听端口,等待客户端程序的连接。客户端程序发起连接,等待服务端的相应。客户端想要连接上服务端的话,需要 知道服务端的ip地址。
例如,客户想要访问百度网站的首页,通过浏览器访问http://www.baidu.com。浏览器发出请求之后,先是DNS服务器将百度的域名解析成ip地址之后,访问到ip地址为115.239.210.27服务器的80端口(http协议默认在80端口),请求发送后,百度的服务器作为响应将页面的源代码发送至客户端(通过浏览器右键->源代码,或者ctrl+u可以看到服务器返回的页面源代码),随后浏览器将源代码渲染成页面。这样用户就看到了百度网站的首页。
头文件和库文件
在windows系统上,当前的Windows Socket接口是Windows Sockets 2,所有接口函数都是有Ws2_32.dll导出。在进行程序设计时,祥光的数据类型、结构定义、函数声明等卫浴头文件winsock2.h中,编译时需要包含此文件,并且连接到库Ws2_32.lib。
常用函数
常见的socket函数
WSAStartup () 函数
WSAStartup函数的功能使加载Ws2_32.dll等Socket程序运行的环境。在程序初始化后,Socket程序运行所依赖的动态链接库不一定已经在家,WSAStartup保证了Socket 动态链接库的加载。
1
2
3
4
|
int
__in WORD
__out ); |
参数一 wVersionRequested
Socket程序库的版本,一般使用MAKEWORD(2,2)宏生成。
参数二 lpWSAData
输出参数,指向 WSADATA 结构的指针,用于返回Socket库初始化的信息。
返回值 用来判断程序是否成功加载
WSACleanup () 函数
与 WSAStartup 相反, WSACleanup 释放Ws2_32.dll,函数无参数。
Socket () 函数
Socket函数的功能是建立一个绑定到制定协议和传输类型的Socket。
1
2
3
4
5
|
SOCKET __in int
__in int
__in int
); |
参数一 af
address family的缩写,制定该Socket使用哪一种类型的网络地址。可以是IPv4(AF_INET),也可以是IPv6(AF_INET6)、蓝牙(AF_BTM)、NetBios(AF_NETBIOS)等。
参数二 type
设置传输类型,常见类型有 SOCK_STREAM、 SOCK_DGRAM、 SOCK_RAM、 SOCK_SEQPACKET 等。SOCK_STREAM 类型是基于连接的(TCP),所收的数据时数据流形式的,传输层的数据包已经经过处理。SOCK_DGRAM是基于报文(UDP)。如果制定为SOCK_RAM,那么可以建立原始套接字,所收到的数据是以数据包(包括包头)的形式存在的。
参数三 protocol
设置传输协议,常用的协议为 IPPROTO_TCP 和 IPPROTO_UDP。
colsesocket() 函数
与 socket 函数对应,用于关闭 socket
1
2
3
|
int
__in ); |
参数一 s
指定要关闭的socket
sockaddr 和 sockaddr_in 结构体
sockaddr、 SOCKADDR、 sockaddr_in、 SOCKADDR_IN 这
几个结构用于表示地址很端口。在IPv4下,这几个结构体是可以通用的。
1
2
3
4
5
6
7
8
9
10
|
typedef
#if u_short #else ADDRESS_FAMILY // #endif CHAR
// } |
1
2
3
4
5
6
7
8
9
10
11
12
|
typedef
#if(_WIN32_WINNT short
#else ADDRESS_FAMILY #endif USHORT
IN_ADDR CHAR
} |
bind() 函数
服务器端,将Socket与网络地址和端口绑定起来,函数原型如下:
1
2
3
4
5
|
int
__in __in_bcount(namelen) const
__in int
); |
参数一 s
要绑定的socket
参数二 name
要绑定的网络地址结构体
参数三 namelen
name参数所指向的结构体的大小
listen() 函数
设置 socket 的状态为监听,使客户端程序可以进行连接,函数原型:
1
2
3
4
|
int
__in __in int
); |
参数一 s
绑定的socket
参数二 backlog
指定最大的连接数
accept() 函数
接受客户端的连接
1
2
3
4
5
|
SOCKET __in __out_bcount_opt(*addrlen) struct
__inout_opt int
); |
参数一 s
正在监听的socket,该 socket 使用 listen() 设置。
参数二 addr (可选)
指针,指向一缓冲区,其中接收为通讯层所知的连接实体的地址。Addr参数的实际格式由套接口创建时所产生的地址族确定。
参数三 addrlen (可选)
指针,指向存有addr地址长度的整形数。
返回:
成功:非负描述字
失败:-1
accept 默认会阻塞进程,直到有客户端建立连接后返回,它返回的是连接用的 socket 。如果 accept 成功返回,则服务器与客户已经正确建立连接了,此时服务器通过 accept 返回的 socket 来完成与客户的通信。
connect() 函数
connect函数的功能使与服务器建立连接。这个函数只能由客户端程序调用。
1
2
3
4
5
|
int
__in __in_bcount(namelen) const
__in int
); |
参数一 s
由 socket 函数建立的套接字。
参数二 name
指向sockaddr结构体指针,包括了所要连接的服务端的地址和端口等。
参数三 namelen
sockaddr结构的长度
send() 函数
向连接的另一端发送数据,不论是客户还是服务器应用程序都用 send 函数来向 TCP 连接的另一端发送数据。
1
2
3
4
5
6
|
int
__in __in_bcount(len) const
__in int
__in int
); |
参数一 s
指定发送端socket描述符。
参数二 *buf
指明存放要发送的数据的缓冲区。
参数三 len
指明实际要发送的数据的字节数。
参数四 flags
指明发送的方法,常见宏MSG_DONTROUTE、MSG_OOB等,一般置0。
将*buf指向的字符串发送至客户端
recv() 函数
不论是客户还是服务器应用程序都用 recv 函数 从 TCP 连接的另一端接收数据。
1
2
3
4
5
6
|
int
__in __out_bcount_part(len, return ) char
__in int
__in int
); |
参数一 s
指定接收端socket描述符;
参数二 *buf
指明一个缓冲区,该缓冲区用来存放recv函数接收到的数据;
参数三 len
指明buf的长度;
参数四 flags
指明接收的方法,常见宏 MSG_DONTROUTE、 MSG_OOB 等,一般置0。
获取到客户端返回的字符串并将其写入到buf中
简单的 socket 通信示例
服务端(Server)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
#include #include #pragma void
{ int
// int
char
// char
// SOCKET // SOCKADDR_IN // SOCKET // SOCKADDR_IN // WSADATA // WORD
// // wVersionRequested // err if
{ // return ; } /* * * * */ if
{ // WSACleanup(); // return ; } // sockServer // addrServer.sin_addr.S_un.S_addr // addrServer.sin_family // addrServer.sin_port // // bind(sockServer, sizeof (SOCKADDR)); // listen(sockServer, // printf ( "服务器已启动:\n监听中...\n" ); len sizeof (SOCKADDR); // sockClient // sprintf (sendBuf, "欢迎 , // send(sockClient, strlen (sendBuf) // recv(sockClient, // printf ( "%s\n" , // closesocket(sockClient); getchar (); } |
启动后防火墙有阻挡提示,这里接受就可以了。另外下图是原来博主测试时截的图,跟上面代码的输出部分稍稍有些区别。
客户端(Client)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
#include #include #pragma void
{ int
char
char
SOCKET // SOCKADDR_IN // WSADATA WORD
wVersionRequested err if
{ return ; } if
{ // WSACleanup( return ; } // sockClient // addrServer.sin_addr.S_un.S_addr "127.0.0.1" ); // addrServer.sin_family // addrServer.sin_port // // connect(sockClient, sizeof (SOCKADDR)); // recv(sockClient, // printf ( "%s\n" , message "服务端你好~" ; // send(sockClient, strlen (message) // closesocket(sockClient); WSACleanup(); getchar (); // } |
客户端与服务端更多通信,例子:《木马,你好!(二)最简单的木马》
简单的端口扫描程序
hostent结构体
host entry的缩写,该结构记录主机的信息,包括主机名、别名、地址类型、地址长度和地址列表。之所以主机的地址是一个列表的形式,原因是当一个主机有多个网络接口时会有多个地址。
1
2
3
4
5
6
7
8
|
struct
char
/* char
/* short
/* short
/* char
/* #define }; |
代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
#include #include #include #pragma void
void
int
int
char
{ WORD
WSADATA //sockaddr_in结构体 struct
sin ; int
int
int
char
HOSTENT char
char
SOCKET int
int
if
{ Help(); return
} iFromPort atoi (argv[2]); iToPort atoi (argv[3]); host_name if
{ printf ( "起始端口不能大于结束端口,且范围为:1--65535 ); return
} if
{ printf ( "初始化失败!" ); return
} // host_entry if
{ wsprintf( "%d.%d.%d.%d" , (host_entry->h_addr_list[0][0] (host_entry->h_addr_list[0][1] (host_entry->h_addr_list[0][2] (host_entry->h_addr_list[0][3] ); printf ( "\n主机名称:%s , } cHost printf ( "======= ); for
{ s if
{ printf ( "create ); WSACleanup(); } sin .sin_family sin .sin_port sin .sin_addr.S_un.S_addr if
struct
sin , sizeof ( sin )) { printf ( "%s , closesocket(s); } else { printf ( "%s , port[iOpenPort] iOpenPort closesocket(s); } } printf ( "======= ); printf ( "主机:%s , for
{ printf ( "%d , } //关闭socket closesocket(s); WSACleanup(); return
} //帮助函数 void
{ printf ( "Usage: ); printf ( "Port.exe ); printf ( "Example: ); printf ( "scan.exe ); } |
函数列表
一、基本Socket函数
二、获取信息
三、DLL操作
Windows API 教程(九) 网络编程的更多相关文章
- Windows API教程文件系统
本篇文章主要介绍了"Windows API教程文件系统",主要涉及到Windows API教程文件系统方面的内容,对于Windows API教程文件系统感兴趣的同学可以参考一下. ...
- Java基础教程:网络编程
Java基础教程:网络编程 基础 Socket与ServerSocket Socket又称"套接字",网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个s ...
- windows下的socket网络编程
windows下的socket网络编程 windows下的socket网络编程 clinet.c 客户端 server.c 服务器端 UDP通信的实现 代码如下 已经很久没有在windows下编程了, ...
- windows下的socket网络编程(入门级)
windows下的socket网络编程 clinet.c 客户端 server.c 服务器端 UDP通信的实现 代码如下 已经很久没有在windows下编程了,这次因为需要做一个跨平台的网络程序,就先 ...
- Java之旅_高级教程_网络编程
摘自:http://www.runoob.com/java/java-networking.html JAVA网络编程 网络编程是指编写运行在多个设备(计算机)的程序,这些设备都通过网络连接起来. j ...
- Windows Embedded Compact 7网络编程概述(上)
如今,不论是嵌入式设备.PDA还是智能手机,网络都是必不可少的模块.网络使人们更方便地共享设备上的信息和资源.而且,利用智能手机浏览互联网,也逐渐成为生活中的常见手段.物联网所倡导的物物相联,也离不开 ...
- Windows Embedded Compact 7网络编程概述(下)
11.1.1 Select I/O模型 在Windows CE中,Select模型是唯一被支持的I/O模型.Select I/O模型就是利用select函数对I/O进行管理. 函数select的功能在 ...
- Windows API 教程(七) hook 钩子监听
茵蒂克丝 如何创建一个窗口 手动创建窗口的流程 实际代码 安装钩子 (Install hook) 钩子简介 SetWindowsHookEx 函数 设置监听[键盘]消息 设置监听[鼠标]消息 如何创建 ...
- Java入门 - 高级教程 - 05.网络编程
原文地址:http://www.work100.net/training/java-networking.html 更多教程:光束云 - 免费课程 网络编程 序号 文内章节 视频 1 概述 2 Soc ...
- C++使用Windows API CreateMutex函数多线程编程
C++中也可以使用Windows 系统中对应的API函数进行多线程编程.使用CreateThread函数创建线程,并且可以通过CreateMutex创建一个互斥量实现线程间数据的同步: #includ ...
随机推荐
- IDEA模板快捷键
2.1 psvm:可生成 main 方法 2.2 sout:System.out.println() 快捷输出 类似的: soutp=System.out.println("方法形参名 = ...
- 力扣208——实现 Trie (前缀树)
这道题主要是构造前缀树节点的数据结构,帮助解答问题. 原题 实现一个 Trie (前缀树),包含 insert, search, 和 startsWith 这三个操作. 示例: Trie trie = ...
- 《图解机器学习-杉山将著》读书笔记---CH5
CH5 稀疏学习 重点提炼 提出稀疏学习的缘故: 虽然带有约束条件的最小二乘学习法结合交叉验证法,在实际应用中是非常有效的回归方法,但是,当参数特别多时,计算参数以及预测值需要大量时间.此时,我们要解 ...
- Spring Boot2 系列教程(三十一)Spring Boot 构建 RESTful 风格应用
RESTful ,到现在相信已经没人不知道这个东西了吧!关于 RESTful 的概念,我这里就不做过多介绍了,传统的 Struts 对 RESTful 支持不够友好 ,但是 SpringMVC 对于 ...
- Tomcat的性能优化及JVM内存工作原理
JVM性能优化原则:代码运算性能.内存回收.应用配置(影响Java程序主要原因是垃圾回收机制)代码层优化:避免过多循环嵌套.调用和复杂逻辑. Tomcat调优主要内容 1.增加最大连接数 2.调整工作 ...
- Redis系列之----Redis的两种持久化机制(RDB和AOF)
Redis的两种持久化机制(RDB和AOF) 什么是持久化 Redis的数据是存储在内存中的,内存中的数据随着服务器的重启或者宕机便会不复存在,在生产环境,服务器宕机更是屡见不鲜,所以,我们希望 ...
- Java8 新特性(三) - 日期时间对象以及一些其他特性
日期时间对象 关于日期时间的操作可以分为两种: 转换:与字符串的互相转换,与时间戳的互相转换 计算:计算两个时间点之间的间隔.时间点与时间段的计算(计算下周N.下个月D日.去年M月D日等等) Java ...
- Java单体应用 - 导读
原文地址:http://www.work100.net/training/monolithic 更多教程:光束云 - 免费课程 Java单体应用 本阶段课程将学习如何进行Java单体Web应用开发,经 ...
- 国产CPU 申威1621 异数OS基础组件理论性能测试报告
国产CPU 申威1621 异数OS基础组件理论性能测试报告 文章目录 国产CPU 申威1621 异数OS基础组件理论性能测试报告 前言 测试平台 测试项目 SW1621 异数OS 容器虚拟交换机模拟性 ...
- mybatis in查询
原文地址:https://blog.csdn.net/u012427355/article/details/79580561 foreach的主要用在构建in条件中,它可以在SQL语句中进行迭代一个集 ...