├── LICENSE
├── README.md
├── image
├── Async.jpg
├── Client.gif
├── Server.gif
├── SockAsyncSelectCompletion.png
├── SockProcessAsyncSelect.png
└── complet.jpg
└── src
├── Share.h
├── WSPCS.cpp
├── WSPCS.h
├── WSPSocket.cpp
├── WSPSocket.h
├── socket.cpp
├── socket.sln
├── socket.vcxproj
├── socket.vcxproj.filters
└── socket.vcxproj.user
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 A-Normal-User
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # NtSocket_NtClient_NtServer:
2 | - Using NtCreateFile and NtDeviceIoControlFile to realize the function of winsock
3 | - 利用NtCreateFile和NtDeviceIoControlFile实现winsock的功能。
4 | - 部分功能参考ReactOS源码实现。
5 | - 现在已经成功封装出了一个NtClient和一个NtServer。
6 | - 源码主体实现了以下函数:
7 | - WSPSocket(创建socket句柄)
8 | - WSPCloseSocket(关闭socket)
9 | - WSPBind(Bind一个地址,支持IPv6)
10 | - WSPConnect(连接一个地址,大致用法同Connect函数,支持IPv6)
11 | - WSPShutdown(Shutdown指定操作,可以同WSAShutdown使用)
12 | - WSPListen(基本同Listen函数)
13 | - WSPRecv(接收数据,基本同Recv)
14 | - WSPSend(发送数据,基本同send)
15 | - WSPGetPeerName(基本同GetPeerName,支持IPv6)
16 | - WSPGetSockName(基本同GetSockName,支持IPv6)
17 | - WSPEventSelect(事件选择模型,基本同WSAEventSelect)
18 | - WSPEnumNetworkEvents(事件选择模型,基本同WSAEnumNetworkEvents)
19 | - WSPAccept(基本完整实现accept功能)
20 | - WSPProcessAsyncSelect(本源码最大的亮点,APC异步Select模型,这是winsock没有开放的模型,IOCP模型本质上也依赖这个完成)
21 |
22 | # 前言:
23 | - 本程序只能使用于Windows。
24 | - 本程序开发环境:Win11 x64.
25 | - 本程序理论上兼容x64和x86环境,不过具体出现问题还得具体分析。
26 |
27 | # 为什么写它?
28 | - 之前看了一篇文章:[NTSockets - Downloading a file via HTTP using the NtCreateFile and NtDeviceIoControlFile syscalls](https://www.x86matthew.com/view_post?id=ntsockets "NTSockets - Downloading a file via HTTP using the NtCreateFile and NtDeviceIoControlFile syscalls")
29 | - 我觉得这篇文章非常有意思,**直接利用NtCreateFile和Afd驱动建立通信,然后利用NtDeviceIoControlFile实现向afd发送socket控制的信息**。
30 | - 不过美中不足的是这个程序支持x86(原因是结构体定义的问题),同时也仅实现了Client,其他部分还没有完善。
31 | - 于是便有了这个程序。
32 |
33 | # 正文:
34 | - 最基础的内容,利用NtCreateFile创建socket句柄:
35 | ```cpp
36 | SOCKET WSPSocket(
37 | int AddressFamily,
38 | int SocketType,
39 | int Protocol) {
40 | ///
41 | /// 类似于Socket函数,可以创建一个Socket文件句柄
42 | ///
43 | /// Address family(Support IPv6)
44 | /// Socket Type
45 | /// Protocol type
46 | /// 如果失败返回INVALID_SOCKET,成功返回Socket文件句柄
47 | if (AddressFamily == AF_UNSPEC && SocketType == 0 && Protocol == 0) {
48 | return INVALID_SOCKET;
49 | }
50 | //进行基础数据设置
51 | if (AddressFamily == AF_UNSPEC) {
52 | AddressFamily = AF_INET;
53 | }
54 | if (SocketType == 0)
55 | {
56 | switch (Protocol)
57 | {
58 | case IPPROTO_TCP:
59 | SocketType = SOCK_STREAM;
60 | break;
61 | case IPPROTO_UDP:
62 | SocketType = SOCK_DGRAM;
63 | break;
64 | case IPPROTO_RAW:
65 | SocketType = SOCK_RAW;
66 | break;
67 | default:
68 | SocketType = SOCK_STREAM;
69 | break;
70 | }
71 | }
72 | if (Protocol == 0)
73 | {
74 | switch (SocketType)
75 | {
76 | case SOCK_STREAM:
77 | Protocol = IPPROTO_TCP;
78 | break;
79 | case SOCK_DGRAM:
80 | Protocol = IPPROTO_UDP;
81 | break;
82 | case SOCK_RAW:
83 | Protocol = IPPROTO_RAW;
84 | break;
85 | default:
86 | Protocol = IPPROTO_TCP;
87 | break;
88 | }
89 | }
90 | byte EaBuffer[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x1E, 0x00,
91 | 0x41, 0x66, 0x64, 0x4F, 0x70, 0x65, 0x6E, 0x50,
92 | 0x61, 0x63, 0x6B, 0x65, 0x74, 0x58, 0x58, 0x00,
93 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
94 | 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
95 | 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
96 | 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
97 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
98 | memmove((PVOID)((__int64)EaBuffer + 32), &AddressFamily, 0x4);
99 | memmove((PVOID)((__int64)EaBuffer + 36), &SocketType, 0x4);
100 | memmove((PVOID)((__int64)EaBuffer + 40), &Protocol, 0x4);
101 | if (Protocol == IPPROTO_UDP)
102 | {
103 | memmove((PVOID)((__int64)EaBuffer + 24), &Protocol, 0x4);
104 | }
105 | //初始化UNICODE_STRING:
106 | UNICODE_STRING AfdName;
107 | AfdName.Buffer = L"\\Device\\Afd\\Endpoint";
108 | AfdName.Length = 2 * wcslen(AfdName.Buffer);
109 | AfdName.MaximumLength = AfdName.Length + 2;
110 | OBJECT_ATTRIBUTES Object;
111 | IO_STATUS_BLOCK IOSB;
112 | //初始化OBJECT_ATTRIBUTES
113 | InitializeObjectAttributes(&Object,
114 | &AfdName,
115 | OBJ_CASE_INSENSITIVE | OBJ_INHERIT,
116 | 0,
117 | 0);
118 | HANDLE MySock;
119 | NTSTATUS Status;
120 | //创建AfdSocket:
121 | Status = ((NtCreateFile)MyNtCreateFile)(&MySock,
122 | GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
123 | &Object,
124 | &IOSB,
125 | NULL,
126 | 0,
127 | FILE_SHARE_READ | FILE_SHARE_WRITE,
128 | FILE_OPEN_IF,
129 | 0,
130 | EaBuffer,
131 | sizeof(EaBuffer));
132 | if (Status != STATUS_SUCCESS) {
133 | return INVALID_SOCKET;
134 | }
135 | else {
136 | return (SOCKET)MySock;
137 | }
138 | }
139 | ```
140 | - 从总体上看来,这部分代码是最简单的,用NtCreateFile创建\\Device\\Afd\\Endpoint的连接,麻烦一点的可能是传递的EaBuffer,不过这部分可以直接通过CE拦截的方式获取数据,也可以参考ReactOS的结构体,我选择了一种介于两者之间的方法实现。
141 | - 这部分的兼容性也是最难实现的,因为不知道不同的系统的结构体会不会有差异,不过我测试基本是没有问题的。
142 | - 创建出socket句柄后,剩下的事情就非常简单了,只需要根据不同的“IOCTL_AFD_”写出各个函数即可。
143 | - 最难的部分其实是WSPProcessAsyncSelect函数。
144 | - 这个需要从WSPAsyncSelect函数说起
145 | - 使用IDA看一下mswsock.WSPAsyncSelect函数,大概长这个样子:
146 | - 其中最重要的函数是SockCheckAndInitAsyncSelectHelper:
147 | - SockCheckAndInitAsyncSelectHelper函数先创建了一个\\Device\\Afd\\AsyncSelectHlp的IO(功能未知),**然后用SockCreateAsyncQueuePort函数创建了一个完成端口**
148 | - 接着用NtSetInformationFile函数将完成端口和\\Device\\Afd\\AsyncSelectHlp绑定。
149 | - 在SockAsyncSelectCompletion函数中找到SockProcessAsyncSelect:
150 | - 在SockProcessAsyncSelect中找到AsyncSelect真正实现原理:
151 | - (别问我怎么找的,参看ReactOS源码就会很清晰)
152 | - 图中的操作应该是轮询实现的,效率比较低。
153 | - 不过别忘了,NtDeviceIoControlFile是提供了APCRoutine的接口的。
154 | - **实际上只需要给NtDeviceIoControlFile以APCRoutine接口,就可以实现无需轮询的AsyncSelect**。
155 | - 大致实现:
156 | ```cpp
157 | NTSTATUS WSPProcessAsyncSelect(
158 | SOCKET Handle,
159 | PVOID ApcRoutine,
160 | ULONG lNetworkEvents,
161 | PVOID UserContext
162 | ) {
163 | ///
164 | /// WSPProcessAsyncSelect是本程序最大的亮点,利用异步化的IOCTL_AFD_SELECT
165 | ///
166 | ///
167 | ///
168 | ///
169 | ///
170 | AFD_AsyncData* AsyncData = (AFD_AsyncData*)malloc(sizeof(AFD_AsyncData));
171 | if (AsyncData == NULL)
172 | {
173 | return -1;
174 | }
175 | memset(AsyncData, 0, sizeof(AFD_AsyncData));
176 | AsyncData->NowSocket = Handle;
177 | AsyncData->PollInfo.Timeout.HighPart = 0x7FFFFFFF;
178 | AsyncData->PollInfo.Timeout.LowPart = 0xFFFFFFFF;
179 | AsyncData->PollInfo.HandleCount = 1;
180 | AsyncData->PollInfo.Handle = Handle;
181 | AsyncData->PollInfo.Events = lNetworkEvents;
182 | AsyncData->UserContext = UserContext;
183 | NTSTATUS Status;
184 | Status = ((NtDeviceIoControlFile)(MyNtDeviceIoControlFile))((HANDLE)Handle,
185 | NULL,
186 | ApcRoutine,
187 | AsyncData,
188 | &AsyncData->IOSB,
189 | IOCTL_AFD_SELECT,
190 | &AsyncData->PollInfo,
191 | sizeof(AFD_PollInfo),
192 | &AsyncData->PollInfo,
193 | sizeof(AFD_PollInfo));
194 | return Status;
195 | }
196 | ```
197 | - 既然已经做出了肌醇函数,剩下的就是封装了。
198 | - 我封装了“WSPClient”和“WSPServer”两个类(一个客户端,一个服务端)
199 | - 虽然功能不是很齐全,但是至少是能用的。
200 | - 主体说一下WSPServer的AsyncSelect:
201 | - 核心源码:
202 | ```cpp
203 | VOID __stdcall internal_APCRoutine(
204 | PVOID ApcContext,
205 | PIO_STATUS_BLOCK IoStatusBlock,
206 | PVOID Reserved)
207 | {
208 | ///
209 | /// 这是一个内部函数,也是本程序最大的亮点:APC异步select
210 | /// Client和服务器socket的select情况会全部调用这个函数,本函数用于分发回调事件。
211 | ///
212 | ///
213 | ///
214 | ///
215 | ///
216 | AFD_AsyncData* AsyncData = (AFD_AsyncData*)ApcContext;
217 | //读取出ApcContext,保存的是AsyncData,AsyncData的详细使用情况请看WSPProcessAsyncSelect函数的实现。
218 | WSPServer* self = (WSPServer*)AsyncData->UserContext;
219 | //读取出WSPServer对象,这个主要是读取出回调函数地址。
220 | //然后调用回调函数,参数是socket句柄和事件信息
221 | ((WSPServerCallBack)self->m_CallBack)(AsyncData->NowSocket, AsyncData->PollInfo.Events);
222 | //开启下一次APC异步select
223 | WSPProcessAsyncSelect(AsyncData->NowSocket, internal_APCRoutine, self->m_EnableEvent, (PVOID)self);
224 | //释放掉原来的AsyncData
225 | free(AsyncData);
226 | }
227 |
228 |
229 | VOID WSPServer::internal_APCThread(WSPServer* Server) {
230 | ///
231 | /// 本函数是APC异步select的线程函数,用于开启每个socket的APC异步select
232 | ///
233 | /// WSPServer对象
234 | int i = 0;
235 | while (1) {
236 | EnterCriticalSection(&Server->m_CriticalSection);
237 | if (!Server->IsRun) {
238 | //已经通知本线程退出
239 | LeaveCriticalSection(&Server->m_CriticalSection);
240 | break;
241 | }
242 | i = Server->m_NeedAPCSocket.size();
243 | i--;
244 | for (i; i >= 0; i--) {
245 | //将m_NeedAPCSocket每一socket读取出来,开启APC异步select
246 | WSPProcessAsyncSelect(
247 | Server->m_NeedAPCSocket[i],
248 | internal_APCRoutine,
249 | Server->m_EnableEvent,
250 | (PVOID)Server
251 | );
252 | //后面的APC异步select过程将由函数internal_APCRoutine完成
253 | Server->m_NeedAPCSocket.pop_back();
254 | //删除m_NeedAPCSocket对应的socket
255 | }
256 | LeaveCriticalSection(&Server->m_CriticalSection);
257 | SleepEx(1, true);
258 | }
259 | }
260 |
261 | HANDLE WSPServer::APCAsyncSelect(
262 | WSPServerCallBack* ApcCallBack,
263 | int lNetworkEvents
264 | ) {
265 | ///
266 | /// 开启服务器的APC异步select模式,只能初始化一次
267 | ///
268 | /// 回调函数
269 | /// 需要异步处理的事件
270 | /// 返回异步处理线程的句柄
271 | if (this->m_CallBack != NULL) {
272 | return INVALID_HANDLE_VALUE;
273 | }
274 | EnterCriticalSection(&this->m_CriticalSection);
275 | this->m_EnableEvent = lNetworkEvents;
276 | this->m_CallBack = ApcCallBack;
277 | //下面将把m_AllClientSocket已有的句柄拷贝到m_NeedAPCSocket
278 | std::copy(m_AllClientSocket.begin(), m_AllClientSocket.end(), m_NeedAPCSocket.begin());
279 | //将服务器socket加入m_NeedAPCSocket
280 | m_NeedAPCSocket.push_back(this->m_socket);
281 | //启动线程
282 | m_ThreadHandle = CreateThread(NULL, 0, (PTHREAD_START_ROUTINE)internal_APCThread, this, 0, NULL);
283 | LeaveCriticalSection(&this->m_CriticalSection);
284 | return m_ThreadHandle;
285 | }
286 | ```
287 | - 就是利用WSPProcessAsyncSelect函数实现APC异步选择
288 | - 当select状态改变时,程序会通知internal_APCRoutine,internal_APCRoutine再进行回调函数的分发和下一次AsyncSelect的调用。
289 | - 写得不是很精简,勉强能用吧。
290 | - 这种APC方法省去了IOCP模型中很多复杂的步骤,可以说是一个最精简的异步模型了。
291 |
292 | # 测试:
293 | - Client端请求`http://www.baidu.com/index.html`测试:
294 | - Server端1000连接测试:
295 | - 测试Server端上万连接,APC效率基本无损失。
296 |
--------------------------------------------------------------------------------
/image/Async.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/A-Normal-User/NtSocket_NtClient_NtServer/2fcfbcc6db893f622914b8c668719c26695a459b/image/Async.jpg
--------------------------------------------------------------------------------
/image/Client.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/A-Normal-User/NtSocket_NtClient_NtServer/2fcfbcc6db893f622914b8c668719c26695a459b/image/Client.gif
--------------------------------------------------------------------------------
/image/Server.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/A-Normal-User/NtSocket_NtClient_NtServer/2fcfbcc6db893f622914b8c668719c26695a459b/image/Server.gif
--------------------------------------------------------------------------------
/image/SockAsyncSelectCompletion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/A-Normal-User/NtSocket_NtClient_NtServer/2fcfbcc6db893f622914b8c668719c26695a459b/image/SockAsyncSelectCompletion.png
--------------------------------------------------------------------------------
/image/SockProcessAsyncSelect.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/A-Normal-User/NtSocket_NtClient_NtServer/2fcfbcc6db893f622914b8c668719c26695a459b/image/SockProcessAsyncSelect.png
--------------------------------------------------------------------------------
/image/complet.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/A-Normal-User/NtSocket_NtClient_NtServer/2fcfbcc6db893f622914b8c668719c26695a459b/image/complet.jpg
--------------------------------------------------------------------------------
/src/Share.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 |
5 | typedef struct _IO_STATUS_BLOCK {
6 | union {
7 | NTSTATUS Status;
8 | PVOID64 Pointer;
9 | } DUMMYUNIONNAME;
10 | ULONG_PTR Information;
11 | } IO_STATUS_BLOCK, * PIO_STATUS_BLOCK;
12 |
13 | #if _WIN64
14 | typedef struct _UNICODE_STRING {
15 | USHORT Length;
16 | USHORT MaximumLength;
17 | ULONG Reserved;
18 | PCWSTR Buffer;
19 | } UNICODE_STRING;
20 | #elif _WIN32
21 | typedef struct _UNICODE_STRING {
22 | USHORT Length;
23 | USHORT MaximumLength;
24 | PCWSTR Buffer;
25 | } UNICODE_STRING;
26 | #endif
27 |
28 | typedef UNICODE_STRING* PUNICODE_STRING;
29 | typedef const UNICODE_STRING* PCUNICODE_STRING;
30 |
31 | typedef struct _OBJECT_ATTRIBUTES {
32 | ULONG Length;
33 | HANDLE RootDirectory;
34 | PUNICODE_STRING ObjectName;
35 | ULONG Attributes;
36 | PVOID SecurityDescriptor; // Points to type SECURITY_DESCRIPTOR
37 | PVOID SecurityQualityOfService; // Points to type SECURITY_QUALITY_OF_SERVICE
38 | } OBJECT_ATTRIBUTES;
39 | typedef OBJECT_ATTRIBUTES* POBJECT_ATTRIBUTES;
40 |
41 | #define OBJ_INHERIT 0x00000002L
42 | #define OBJ_PERMANENT 0x00000010L
43 | #define OBJ_EXCLUSIVE 0x00000020L
44 | #define OBJ_CASE_INSENSITIVE 0x00000040L
45 | #define OBJ_OPENIF 0x00000080L
46 | #define OBJ_OPENLINK 0x00000100L
47 | #define OBJ_KERNEL_HANDLE 0x00000200L
48 | #define OBJ_FORCE_ACCESS_CHECK 0x00000400L
49 | #define OBJ_VALID_ATTRIBUTES 0x000007F2L
50 | #define FILE_OPEN_IF 0x00000003
51 | #define STATUS_SUCCESS 0x0
52 | #define AF_INET6 0x17
53 | #define InitializeObjectAttributes(p,n,a,r,s) { \
54 | (p)->Length = sizeof(OBJECT_ATTRIBUTES); \
55 | (p)->RootDirectory = (r); \
56 | (p)->Attributes = (a); \
57 | (p)->ObjectName = (n); \
58 | (p)->SecurityDescriptor = (s); \
59 | (p)->SecurityQualityOfService = NULL; \
60 | }
61 |
62 | typedef enum _EVENT_TYPE {
63 | NotificationEvent,
64 | SynchronizationEvent
65 | } EVENT_TYPE;
66 | #if _WIN64
67 | typedef NTSTATUS(*NtDeviceIoControlFile)(
68 | HANDLE FileHandle,
69 | HANDLE Event,
70 | PVOID ApcRoutine,
71 | PVOID ApcContext,
72 | PIO_STATUS_BLOCK IoStatusBlock,
73 | ULONG IoControlCode,
74 | PVOID InputBuffer,
75 | ULONG InputBufferLength,
76 | PVOID OutputBuffer,
77 | ULONG OutputBufferLength
78 | );
79 | typedef NTSTATUS(*NtCreateEvent)(
80 | PHANDLE EventHandle,
81 | ACCESS_MASK DesiredAccess,
82 | POBJECT_ATTRIBUTES ObjectAttributes,
83 | EVENT_TYPE EventType,
84 | BOOLEAN InitialState
85 | );
86 | typedef NTSTATUS(*NtCreateFile)(PHANDLE FileHandle,
87 | ACCESS_MASK DesiredAccess,
88 | POBJECT_ATTRIBUTES ObjectAttributes,
89 | PIO_STATUS_BLOCK IoStatusBlock,
90 | PLARGE_INTEGER AllocateSize,
91 | ULONG FileAttributes,
92 | ULONG ShareAccess,
93 | ULONG CreateDisposition,
94 | ULONG CreateOptions,
95 | PVOID EaBuffer,
96 | ULONG EaLength);
97 | typedef NTSTATUS(*RtlIpv6StringToAddressExA) (
98 | PVOID AddressString,
99 | byte* Address,
100 | PULONG ScopeId,
101 | PUSHORT Port
102 | );
103 | #elif _WIN32
104 | typedef NTSTATUS(__stdcall *NtDeviceIoControlFile)(
105 | HANDLE FileHandle,
106 | HANDLE Event,
107 | PVOID ApcRoutine,
108 | PVOID ApcContext,
109 | PIO_STATUS_BLOCK IoStatusBlock,
110 | ULONG IoControlCode,
111 | PVOID InputBuffer,
112 | ULONG InputBufferLength,
113 | PVOID OutputBuffer,
114 | ULONG OutputBufferLength
115 | );
116 | typedef NTSTATUS(__stdcall*NtCreateEvent)(
117 | PHANDLE EventHandle,
118 | ACCESS_MASK DesiredAccess,
119 | POBJECT_ATTRIBUTES ObjectAttributes,
120 | EVENT_TYPE EventType,
121 | BOOLEAN InitialState
122 | );
123 | typedef NTSTATUS(__stdcall*NtCreateFile)(PHANDLE FileHandle,
124 | ACCESS_MASK DesiredAccess,
125 | POBJECT_ATTRIBUTES ObjectAttributes,
126 | PIO_STATUS_BLOCK IoStatusBlock,
127 | PLARGE_INTEGER AllocateSize,
128 | ULONG FileAttributes,
129 | ULONG ShareAccess,
130 | ULONG CreateDisposition,
131 | ULONG CreateOptions,
132 | PVOID EaBuffer,
133 | ULONG EaLength);
134 | typedef NTSTATUS(__stdcall*RtlIpv6StringToAddressExA) (
135 | PVOID AddressString,
136 | byte* Address,
137 | PULONG ScopeId,
138 | PUSHORT Port
139 | );
140 | #endif
141 | /* AFD Packet Endpoint Flags */
142 | #define AFD_ENDPOINT_CONNECTIONLESS 0x1
143 | #define AFD_ENDPOINT_MESSAGE_ORIENTED 0x10
144 | #define AFD_ENDPOINT_RAW 0x100
145 | #define AFD_ENDPOINT_MULTIPOINT 0x1000
146 | #define AFD_ENDPOINT_C_ROOT 0x10000
147 | #define AFD_ENDPOINT_D_ROOT 0x100000
148 |
149 | /* AFD TDI Query Flags */
150 | #define AFD_ADDRESS_HANDLE 0x1L
151 | #define AFD_CONNECTION_HANDLE 0x2L
152 |
153 | /* AFD event bits */
154 | #define AFD_EVENT_RECEIVE_BIT 0
155 | #define AFD_EVENT_OOB_RECEIVE_BIT 1
156 | #define AFD_EVENT_SEND_BIT 2
157 | #define AFD_EVENT_DISCONNECT_BIT 3
158 | #define AFD_EVENT_ABORT_BIT 4
159 | #define AFD_EVENT_CLOSE_BIT 5
160 | #define AFD_EVENT_CONNECT_BIT 6
161 | #define AFD_EVENT_ACCEPT_BIT 7
162 | #define AFD_EVENT_CONNECT_FAIL_BIT 8
163 | #define AFD_EVENT_QOS_BIT 9
164 | #define AFD_EVENT_GROUP_QOS_BIT 10
165 | #define AFD_EVENT_ROUTING_INTERFACE_CHANGE_BIT 11
166 | #define AFD_EVENT_ADDRESS_LIST_CHANGE_BIT 12
167 | #define AFD_MAX_EVENT 13
168 | #define AFD_ALL_EVENTS ((1 << AFD_MAX_EVENT) - 1)
169 |
170 | /* AFD Info Flags */
171 | #define AFD_INFO_INLINING_MODE 0x01L
172 | #define AFD_INFO_BLOCKING_MODE 0x02L
173 | #define AFD_INFO_SENDS_IN_PROGRESS 0x04L
174 | #define AFD_INFO_RECEIVE_WINDOW_SIZE 0x06L
175 | #define AFD_INFO_SEND_WINDOW_SIZE 0x07L
176 | #define AFD_INFO_GROUP_ID_TYPE 0x10L
177 | #define AFD_INFO_RECEIVE_CONTENT_SIZE 0x11L
178 |
179 | /* AFD Share Flags */
180 | #define AFD_SHARE_UNIQUE 0x0L
181 | #define AFD_SHARE_REUSE 0x1L
182 | #define AFD_SHARE_WILDCARD 0x2L
183 | #define AFD_SHARE_EXCLUSIVE 0x3L
184 |
185 | /* AFD Disconnect Flags */
186 | #define AFD_DISCONNECT_SEND 0x01L
187 | #define AFD_DISCONNECT_RECV 0x02L
188 | #define AFD_DISCONNECT_ABORT 0x04L
189 | #define AFD_DISCONNECT_DATAGRAM 0x08L
190 |
191 | /* AFD Event Flags */
192 | #define AFD_EVENT_RECEIVE (1 << AFD_EVENT_RECEIVE_BIT)
193 | #define AFD_EVENT_OOB_RECEIVE (1 << AFD_EVENT_OOB_RECEIVE_BIT)
194 | #define AFD_EVENT_SEND (1 << AFD_EVENT_SEND_BIT)
195 | #define AFD_EVENT_DISCONNECT (1 << AFD_EVENT_DISCONNECT_BIT)
196 | #define AFD_EVENT_ABORT (1 << AFD_EVENT_ABORT_BIT)
197 | #define AFD_EVENT_CLOSE (1 << AFD_EVENT_CLOSE_BIT)
198 | #define AFD_EVENT_CONNECT (1 << AFD_EVENT_CONNECT_BIT)
199 | #define AFD_EVENT_ACCEPT (1 << AFD_EVENT_ACCEPT_BIT)
200 | #define AFD_EVENT_CONNECT_FAIL (1 << AFD_EVENT_CONNECT_FAIL_BIT)
201 | #define AFD_EVENT_QOS (1 << AFD_EVENT_QOS_BIT)
202 | #define AFD_EVENT_GROUP_QOS (1 << AFD_EVENT_GROUP_QOS_BIT)
203 | #define AFD_EVENT_ROUTING_INTERFACE_CHANGE (1 << AFD_EVENT_ROUTING_INTERFACE_CHANGE_BIT)
204 | #define AFD_EVENT_ADDRESS_LIST_CHANGE (1 << AFD_EVENT_ADDRESS_LIST_CHANGE_BIT)
205 |
206 | /* AFD SEND/RECV Flags */
207 | #define AFD_SKIP_FIO 0x1L
208 | #define AFD_OVERLAPPED 0x2L
209 | #define AFD_IMMEDIATE 0x4L
210 |
211 | #define TDI_SEND_EXPEDITED ((USHORT)0x0020) // TSDU is/was urgent/expedited.
212 | #define TDI_SEND_PARTIAL ((USHORT)0x0040) // TSDU is/was terminated by an EOR.
213 | #define TDI_SEND_NO_RESPONSE_EXPECTED ((USHORT)0x0080) // HINT: no back traffic expected.
214 | #define TDI_SEND_NON_BLOCKING ((USHORT)0x0100) // don't block if no buffer space in protocol
215 | #define TDI_SEND_AND_DISCONNECT ((USHORT)0x0200) // Piggy back disconnect to remote and do not
216 | // indicate disconnect from remote
217 | /* IOCTL Generation */
218 | #define FSCTL_AFD_BASE FILE_DEVICE_NETWORK
219 | #define _AFD_CONTROL_CODE(Operation,Method) \
220 | ((FSCTL_AFD_BASE)<<12 | (Operation<<2) | Method)
221 |
222 | /* AFD Commands */
223 | #define AFD_BIND 0
224 | #define AFD_CONNECT 1
225 | #define AFD_START_LISTEN 2
226 | #define AFD_WAIT_FOR_LISTEN 3
227 | #define AFD_ACCEPT 4
228 | #define AFD_RECV 5
229 | #define AFD_RECV_DATAGRAM 6
230 | #define AFD_SEND 7
231 | #define AFD_SEND_DATAGRAM 8
232 | #define AFD_SELECT 9
233 | #define AFD_DISCONNECT 10
234 | #define AFD_GET_SOCK_NAME 11
235 | #define AFD_GET_PEER_NAME 12
236 | #define AFD_GET_TDI_HANDLES 13
237 | #define AFD_SET_INFO 14
238 | #define AFD_GET_CONTEXT_SIZE 15
239 | #define AFD_GET_CONTEXT 16
240 | #define AFD_SET_CONTEXT 17
241 | #define AFD_SET_CONNECT_DATA 18
242 | #define AFD_SET_CONNECT_OPTIONS 19
243 | #define AFD_SET_DISCONNECT_DATA 20
244 | #define AFD_SET_DISCONNECT_OPTIONS 21
245 | #define AFD_GET_CONNECT_DATA 22
246 | #define AFD_GET_CONNECT_OPTIONS 23
247 | #define AFD_GET_DISCONNECT_DATA 24
248 | #define AFD_GET_DISCONNECT_OPTIONS 25
249 | #define AFD_SET_CONNECT_DATA_SIZE 26
250 | #define AFD_SET_CONNECT_OPTIONS_SIZE 27
251 | #define AFD_SET_DISCONNECT_DATA_SIZE 28
252 | #define AFD_SET_DISCONNECT_OPTIONS_SIZE 29
253 | #define AFD_GET_INFO 30
254 | #define AFD_EVENT_SELECT 33
255 | #define AFD_ENUM_NETWORK_EVENTS 34
256 | #define AFD_DEFER_ACCEPT 35
257 | #define AFD_GET_PENDING_CONNECT_DATA 41
258 | #define AFD_VALIDATE_GROUP 42
259 |
260 | /* AFD IOCTLs */
261 |
262 | #define IOCTL_AFD_BIND \
263 | _AFD_CONTROL_CODE(AFD_BIND, METHOD_NEITHER)
264 | #define IOCTL_AFD_CONNECT \
265 | _AFD_CONTROL_CODE(AFD_CONNECT, METHOD_NEITHER)
266 | #define IOCTL_AFD_START_LISTEN \
267 | _AFD_CONTROL_CODE(AFD_START_LISTEN, METHOD_NEITHER)
268 | #define IOCTL_AFD_WAIT_FOR_LISTEN \
269 | _AFD_CONTROL_CODE(AFD_WAIT_FOR_LISTEN, METHOD_BUFFERED )
270 | #define IOCTL_AFD_ACCEPT \
271 | _AFD_CONTROL_CODE(AFD_ACCEPT, METHOD_BUFFERED )
272 | #define IOCTL_AFD_RECV \
273 | _AFD_CONTROL_CODE(AFD_RECV, METHOD_NEITHER)
274 | #define IOCTL_AFD_RECV_DATAGRAM \
275 | _AFD_CONTROL_CODE(AFD_RECV_DATAGRAM, METHOD_NEITHER)
276 | #define IOCTL_AFD_SEND \
277 | _AFD_CONTROL_CODE(AFD_SEND, METHOD_NEITHER)
278 | #define IOCTL_AFD_SEND_DATAGRAM \
279 | _AFD_CONTROL_CODE(AFD_SEND_DATAGRAM, METHOD_NEITHER)
280 | #define IOCTL_AFD_SELECT \
281 | _AFD_CONTROL_CODE(AFD_SELECT, METHOD_BUFFERED )
282 | #define IOCTL_AFD_DISCONNECT \
283 | _AFD_CONTROL_CODE(AFD_DISCONNECT, METHOD_NEITHER)
284 | #define IOCTL_AFD_GET_SOCK_NAME \
285 | _AFD_CONTROL_CODE(AFD_GET_SOCK_NAME, METHOD_NEITHER)
286 | #define IOCTL_AFD_GET_PEER_NAME \
287 | _AFD_CONTROL_CODE(AFD_GET_PEER_NAME, METHOD_NEITHER)
288 | #define IOCTL_AFD_GET_TDI_HANDLES \
289 | _AFD_CONTROL_CODE(AFD_GET_TDI_HANDLES, METHOD_NEITHER)
290 | #define IOCTL_AFD_SET_INFO \
291 | _AFD_CONTROL_CODE(AFD_SET_INFO, METHOD_NEITHER)
292 | #define IOCTL_AFD_GET_CONTEXT_SIZE \
293 | _AFD_CONTROL_CODE(AFD_GET_CONTEXT_SIZE, METHOD_NEITHER)
294 | #define IOCTL_AFD_GET_CONTEXT \
295 | _AFD_CONTROL_CODE(AFD_GET_CONTEXT, METHOD_NEITHER)
296 | #define IOCTL_AFD_SET_CONTEXT \
297 | _AFD_CONTROL_CODE(AFD_SET_CONTEXT, METHOD_NEITHER)
298 | #define IOCTL_AFD_SET_CONNECT_DATA \
299 | _AFD_CONTROL_CODE(AFD_SET_CONNECT_DATA, METHOD_NEITHER)
300 | #define IOCTL_AFD_SET_CONNECT_OPTIONS \
301 | _AFD_CONTROL_CODE(AFD_SET_CONNECT_OPTIONS, METHOD_NEITHER)
302 | #define IOCTL_AFD_SET_DISCONNECT_DATA \
303 | _AFD_CONTROL_CODE(AFD_SET_DISCONNECT_DATA, METHOD_NEITHER)
304 | #define IOCTL_AFD_SET_DISCONNECT_OPTIONS \
305 | _AFD_CONTROL_CODE(AFD_SET_DISCONNECT_OPTIONS, METHOD_NEITHER)
306 | #define IOCTL_AFD_GET_CONNECT_DATA \
307 | _AFD_CONTROL_CODE(AFD_GET_CONNECT_DATA, METHOD_NEITHER)
308 | #define IOCTL_AFD_GET_CONNECT_OPTIONS \
309 | _AFD_CONTROL_CODE(AFD_GET_CONNECT_OPTIONS, METHOD_NEITHER)
310 | #define IOCTL_AFD_GET_DISCONNECT_DATA \
311 | _AFD_CONTROL_CODE(AFD_GET_DISCONNECT_DATA, METHOD_NEITHER)
312 | #define IOCTL_AFD_GET_DISCONNECT_OPTIONS \
313 | _AFD_CONTROL_CODE(AFD_GET_DISCONNECT_OPTIONS, METHOD_NEITHER)
314 | #define IOCTL_AFD_SET_CONNECT_DATA_SIZE \
315 | _AFD_CONTROL_CODE(AFD_SET_CONNECT_DATA_SIZE, METHOD_NEITHER)
316 | #define IOCTL_AFD_SET_CONNECT_OPTIONS_SIZE \
317 | _AFD_CONTROL_CODE(AFD_SET_CONNECT_OPTIONS_SIZE, METHOD_NEITHER)
318 | #define IOCTL_AFD_SET_DISCONNECT_DATA_SIZE \
319 | _AFD_CONTROL_CODE(AFD_SET_DISCONNECT_DATA_SIZE, METHOD_NEITHER)
320 | #define IOCTL_AFD_SET_DISCONNECT_OPTIONS_SIZE \
321 | _AFD_CONTROL_CODE(AFD_SET_DISCONNECT_OPTIONS_SIZE, METHOD_NEITHER)
322 | #define IOCTL_AFD_GET_INFO \
323 | _AFD_CONTROL_CODE(AFD_GET_INFO, METHOD_NEITHER)
324 | #define IOCTL_AFD_EVENT_SELECT \
325 | _AFD_CONTROL_CODE(AFD_EVENT_SELECT, METHOD_NEITHER)
326 | #define IOCTL_AFD_DEFER_ACCEPT \
327 | _AFD_CONTROL_CODE(AFD_DEFER_ACCEPT, METHOD_NEITHER)
328 | #define IOCTL_AFD_GET_PENDING_CONNECT_DATA \
329 | _AFD_CONTROL_CODE(AFD_GET_PENDING_CONNECT_DATA, METHOD_NEITHER)
330 | #define IOCTL_AFD_ENUM_NETWORK_EVENTS \
331 | _AFD_CONTROL_CODE(AFD_ENUM_NETWORK_EVENTS, METHOD_NEITHER)
332 | #define IOCTL_AFD_VALIDATE_GROUP \
333 | _AFD_CONTROL_CODE(AFD_VALIDATE_GROUP, METHOD_NEITHER)
334 |
--------------------------------------------------------------------------------
/src/WSPCS.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/A-Normal-User/NtSocket_NtClient_NtServer/2fcfbcc6db893f622914b8c668719c26695a459b/src/WSPCS.cpp
--------------------------------------------------------------------------------
/src/WSPCS.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "WSPSocket.h"
3 | #include
4 | #pragma comment (lib, "ws2_32.lib")
5 |
6 | typedef VOID (*WSPServerCallBack)(SOCKET s, int Event);
7 |
8 | class WSPClient
9 | {
10 | private:
11 | CRITICAL_SECTION m_CriticalSection;
12 | public:
13 | WSPClient() {
14 | memset(&m_CriticalSection, 0, sizeof(m_CriticalSection));
15 | }
16 | ~WSPClient();
17 | SOCKET m_socket = NULL;
18 | bool m_EnableIPv6 = false;
19 |
20 | public:
21 | SOCKET InitialSocket(bool EnableIPv6 = false);
22 | VOID DeleteSocket();
23 | NTSTATUS Connect(
24 | char* ConnectAddr,
25 | USHORT Port
26 | );
27 | NTSTATUS ShutDown(
28 | int HowTo
29 | );
30 | NTSTATUS Send(
31 | PVOID lpBuffer,
32 | DWORD lpNumberOfsent
33 | );
34 | NTSTATUS Recv(
35 | PVOID lpBuffer,
36 | DWORD lpNumberOfRecv
37 | );
38 |
39 | };
40 |
41 | class WSPServer
42 | {
43 | public:
44 | CRITICAL_SECTION m_CriticalSection;
45 | int m_EnableEvent = 0;
46 | std::vector m_NeedAPCSocket;
47 | std::vector m_AllClientSocket;
48 | WSPServerCallBack* m_CallBack = NULL;
49 | HANDLE m_ThreadHandle = NULL;
50 | SOCKET m_socket = NULL;
51 | bool m_EnableIPv6 = false;
52 | bool IsRun = false;
53 | public:
54 | WSPServer() {
55 | memset(&m_CriticalSection, 0, sizeof(m_CriticalSection));
56 | }
57 | ~WSPServer();
58 |
59 | public:
60 | SOCKET InitialSocket(bool EnableIPv6 = false);
61 | VOID DeleteSocket();
62 | NTSTATUS CreateServer(
63 | USHORT port,
64 | int backlog = 5
65 | );
66 | SOCKET AcceptClient(
67 | sockaddr_in4* IPv4Addr = NULL,
68 | sockaddr_in6* IPv6Addr = NULL
69 | );
70 | NTSTATUS ShutDown(
71 | SOCKET Handle,
72 | int HowTo
73 | );
74 | NTSTATUS CloseClient(
75 | SOCKET Handle
76 | );
77 | NTSTATUS Send(
78 | SOCKET Handle,
79 | PVOID lpBuffer,
80 | DWORD lpNumberOfsent
81 | );
82 | NTSTATUS Recv(
83 | SOCKET Handle,
84 | PVOID lpBuffer,
85 | DWORD lpNumberOfRecv
86 | );
87 | HANDLE APCAsyncSelect(
88 | WSPServerCallBack* ApcCallBack,
89 | int lNetworkEvents
90 | );
91 |
92 | static VOID internal_APCThread(WSPServer* Server);
93 |
94 | };
95 |
--------------------------------------------------------------------------------
/src/WSPSocket.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/A-Normal-User/NtSocket_NtClient_NtServer/2fcfbcc6db893f622914b8c668719c26695a459b/src/WSPSocket.cpp
--------------------------------------------------------------------------------
/src/WSPSocket.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "Share.h"
3 | struct sockaddr_in4 {
4 | short sin_family;
5 | u_short sin_port;
6 | ULONG sin_addr;
7 | char sin_zero[8];
8 | };
9 |
10 | struct sockaddr_in6 {
11 | USHORT sin6_family;
12 | USHORT sin6_port;
13 | ULONG sin6_flowinfo;
14 | byte sin6_addr[16];
15 | ULONG sin6_scope_id;
16 | };
17 |
18 | struct AFD_BindData {
19 | ULONG ShareType;
20 | sockaddr Address;
21 | };
22 |
23 | struct AFD_BindData_IPv6 {
24 | ULONG ShareType;
25 | sockaddr_in6 Address;
26 | };
27 |
28 | struct AFD_ConnctInfo{
29 | size_t UseSAN;
30 | size_t Root;
31 | size_t Unknown;
32 | sockaddr Address;
33 | };
34 |
35 | struct AFD_ConnctInfo_IPv6 {
36 | size_t UseSAN;
37 | size_t Root;
38 | size_t Unknown;
39 | sockaddr_in6 Address;
40 | };
41 |
42 | struct AFD_Wsbuf {
43 | UINT len;
44 | PVOID buf;
45 | };
46 |
47 | struct AFD_SendRecvInfo {
48 | PVOID BufferArray;
49 | ULONG BufferCount;
50 | ULONG AfdFlags;
51 | ULONG TdiFlags;
52 | };
53 |
54 | struct AFD_ListenInfo {
55 | BOOLEAN UseSAN;
56 | ULONG Backlog;
57 | BOOLEAN UseDelayedAcceptance;
58 | };
59 |
60 | struct AFD_EventSelectInfo {
61 | HANDLE EventObject;
62 | ULONG Events;
63 | };
64 |
65 | struct AFD_EnumNetworkEventsInfo {
66 | ULONG Event;
67 | ULONG PollEvents;
68 | NTSTATUS EventStatus[12];
69 | };
70 |
71 | struct AFD_AcceptData {
72 | ULONG UseSAN;
73 | ULONG SequenceNumber;
74 | HANDLE ListenHandle;
75 | };
76 |
77 | struct AFD_PollInfo{
78 | LARGE_INTEGER Timeout;
79 | ULONG HandleCount;
80 | ULONG Exclusive;
81 | SOCKET Handle;
82 | ULONG Events;
83 | NTSTATUS Status;
84 | };
85 |
86 | struct AFD_AsyncData {
87 | SOCKET NowSocket;
88 | PVOID UserContext;
89 | IO_STATUS_BLOCK IOSB;
90 | AFD_PollInfo PollInfo;
91 | };
92 |
93 | void WSPInit();
94 |
95 | SOCKET WSPSocket(
96 | int AddressFamily,
97 | int SocketType,
98 | int Protocol
99 | );
100 |
101 | NTSTATUS WSPCloseSocket(
102 | SOCKET Handle
103 | );
104 | NTSTATUS WSPBind(
105 | SOCKET Handle,
106 | sockaddr* SocketAddress,
107 | int ShareType
108 | );
109 |
110 | NTSTATUS WSPBind_IPv6(
111 | SOCKET Handle,
112 | sockaddr_in6* SocketAddress,
113 | int ShareType
114 | );
115 |
116 | NTSTATUS WSPConnect(
117 | SOCKET Handle,
118 | sockaddr* SocketAddress
119 | );
120 |
121 | NTSTATUS WSPConnect_IPv6(
122 | SOCKET Handle,
123 | sockaddr_in6* SocketAddress
124 | );
125 |
126 | NTSTATUS WSPListen(
127 | SOCKET Handle,
128 | int Backlog
129 | );
130 |
131 | NTSTATUS WSPRecv(
132 | SOCKET Handle,
133 | PVOID lpBuffers,
134 | PDWORD lpNumberOfBytesRead
135 | );
136 |
137 | NTSTATUS WSPSend(
138 | SOCKET Handle,
139 | PVOID lpBuffers,
140 | DWORD lpNumberOfBytesSent,
141 | DWORD iFlags
142 | );
143 |
144 | NTSTATUS WSPGetPeerName(
145 | SOCKET Handle,
146 | sockaddr_in4* Name
147 | );
148 |
149 | NTSTATUS WSPGetPeerName_IPv6(
150 | SOCKET Handle,
151 | sockaddr_in6* Name
152 | );
153 |
154 | NTSTATUS WSPGetSockName(
155 | SOCKET Handle,
156 | sockaddr_in4* Name
157 | );
158 |
159 | NTSTATUS WSPGetSockName_IPv6(
160 | SOCKET Handle,
161 | sockaddr_in6* Name
162 | );
163 |
164 | NTSTATUS WSPEventSelect(
165 | SOCKET Handle,
166 | HANDLE* hEventObject,
167 | ULONG lNetworkEvents
168 | );
169 |
170 | NTSTATUS WSPEnumNetworkEvents(
171 | SOCKET Handle,
172 | HANDLE hEventObject,
173 | PULONG lpNetworkEvents
174 | );
175 |
176 | SOCKET WSPAccept(
177 | SOCKET Handle,
178 | sockaddr_in4* SocketAddress,
179 | int AddressFamily,
180 | int SocketType,
181 | int Protocol
182 | );
183 |
184 | SOCKET WSPAccept_IPv6(
185 | SOCKET Handle,
186 | sockaddr_in6* SocketAddress,
187 | int AddressFamily,
188 | int SocketType,
189 | int Protocol
190 | );
191 |
192 | NTSTATUS WSPProcessAsyncSelect(
193 | SOCKET Handle,
194 | PVOID ApcRoutine,
195 | ULONG lNetworkEvents,
196 | PVOID UserContext = NULL
197 | );
198 |
199 | NTSTATUS WSPShutdown(
200 | SOCKET Handle,
201 | int HowTo
202 | );
203 |
204 | NTSTATUS inet_addr_IPv6(char* p,
205 | byte* sin6_addr
206 | );
207 |
208 | NTSTATUS inet_addr_IPv6(const char* p,
209 | byte* sin6_addr
210 | );
--------------------------------------------------------------------------------
/src/socket.cpp:
--------------------------------------------------------------------------------
1 | // socket.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
2 | //
3 | #include
4 | #include "WSPCS.h"
5 | using namespace std;
6 |
7 | VOID Callback(SOCKET s, int Event);
8 | VOID ServerTest();
9 | VOID ClientTest();
10 |
11 | WSPServer MyServer;
12 |
13 | int main()
14 | {
15 | WSPInit();//必须先初始化
16 | cout << "输入s启动服务器,输入c启动客户端:";
17 | char c;
18 | cin >> c;
19 | if (c == 's') {
20 | ServerTest();
21 | }
22 | else {
23 | ClientTest();
24 | }
25 | }
26 |
27 | VOID ClientTest() {
28 | WSPClient MyClient;
29 | MyClient.InitialSocket();
30 | //
31 | char Addr[] = "14.215.177.39";
32 | MyClient.Connect(&Addr[0], 80);
33 | char GetRequst[] = "GET /index.html HTTP/1.1\r\nAccept: text/htm\r\nAccept-Language: zh-CN\r\nConnection: keep-alive\r\nHost: www.baidu.com\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36 Edg/105.0.1343.27\r\n\r\n";
34 | MyClient.Send(&GetRequst[0], sizeof(GetRequst));
35 | byte RecvReslut[1024];
36 | memset(&RecvReslut, 0, sizeof(RecvReslut));
37 | MyClient.Recv(RecvReslut, 1024);
38 | cout << "收到的结果是:\r\n" << RecvReslut;
39 | }
40 |
41 | VOID ServerTest() {
42 | NTSTATUS Status;
43 | MyServer.InitialSocket(false);
44 | Status = MyServer.CreateServer(8848, 256);
45 | if (Status != 0) {
46 | cout << "启动MyServer监听8848端口失败!\n";
47 | MyServer.DeleteSocket();
48 | return;
49 | }
50 | cout << "开始监听0.0.0.0:8848\n";
51 | MyServer.APCAsyncSelect((WSPServerCallBack*)Callback, AFD_EVENT_RECEIVE | AFD_EVENT_ACCEPT | AFD_EVENT_DISCONNECT | AFD_EVENT_ABORT | AFD_EVENT_CLOSE);
52 | system("pause");
53 | }
54 | VOID Callback(SOCKET s, int Event) {
55 | if (Event & AFD_EVENT_ACCEPT) {
56 | SOCKET news = MyServer.AcceptClient();
57 | cout << "新用户进入,socket句柄:" << news << "\n";
58 | }
59 | if (Event & AFD_EVENT_RECEIVE) {
60 | PVOID Buffer = malloc(1024);
61 | memset(Buffer, 0, 1024);
62 | MyServer.Recv(s, Buffer,1024);
63 | const char* feedback = "Hello,World!";
64 | MyServer.Send(s, (PVOID)feedback, strlen(feedback));
65 | cout << "收到消息!已经发送回复消息\n";
66 | }
67 | if (Event & AFD_EVENT_DISCONNECT || Event & AFD_EVENT_ABORT || Event & AFD_EVENT_CLOSE) {
68 | if (s == MyServer.m_socket) {
69 | cout << "服务器被销毁\n";
70 | return;
71 | }
72 | MyServer.CloseClient(s);
73 | cout << "断开连接,socket句柄:" << s << "\n";
74 | }
75 | }
--------------------------------------------------------------------------------
/src/socket.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.3.32825.248
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "socket", "socket.vcxproj", "{BDCBBAF7-9478-4D3C-A1F1-A5F74D4DBEA5}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|x64 = Debug|x64
11 | Debug|x86 = Debug|x86
12 | Release|x64 = Release|x64
13 | Release|x86 = Release|x86
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {BDCBBAF7-9478-4D3C-A1F1-A5F74D4DBEA5}.Debug|x64.ActiveCfg = Debug|x64
17 | {BDCBBAF7-9478-4D3C-A1F1-A5F74D4DBEA5}.Debug|x64.Build.0 = Debug|x64
18 | {BDCBBAF7-9478-4D3C-A1F1-A5F74D4DBEA5}.Debug|x86.ActiveCfg = Debug|Win32
19 | {BDCBBAF7-9478-4D3C-A1F1-A5F74D4DBEA5}.Debug|x86.Build.0 = Debug|Win32
20 | {BDCBBAF7-9478-4D3C-A1F1-A5F74D4DBEA5}.Release|x64.ActiveCfg = Release|x64
21 | {BDCBBAF7-9478-4D3C-A1F1-A5F74D4DBEA5}.Release|x64.Build.0 = Release|x64
22 | {BDCBBAF7-9478-4D3C-A1F1-A5F74D4DBEA5}.Release|x86.ActiveCfg = Release|Win32
23 | {BDCBBAF7-9478-4D3C-A1F1-A5F74D4DBEA5}.Release|x86.Build.0 = Release|Win32
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {893559AB-82C2-49A9-8454-CD54BF5B401B}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/src/socket.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | 16.0
23 | Win32Proj
24 | {bdcbbaf7-9478-4d3c-a1f1-a5f74d4dbea5}
25 | socket
26 | 10.0
27 |
28 |
29 |
30 | Application
31 | true
32 | v143
33 | Unicode
34 |
35 |
36 | Application
37 | false
38 | v143
39 | true
40 | Unicode
41 |
42 |
43 | Application
44 | true
45 | v143
46 | Unicode
47 |
48 |
49 | Application
50 | false
51 | v143
52 | true
53 | Unicode
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | Level3
76 | true
77 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
78 | true
79 |
80 |
81 | Console
82 | true
83 |
84 |
85 |
86 |
87 | Level3
88 | true
89 | true
90 | true
91 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
92 | true
93 |
94 |
95 | Console
96 | true
97 | true
98 | true
99 |
100 |
101 |
102 |
103 | Level3
104 | true
105 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
106 | true
107 |
108 |
109 | Console
110 | true
111 |
112 |
113 |
114 |
115 | Level3
116 | true
117 | true
118 | true
119 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
120 | true
121 |
122 |
123 | Console
124 | true
125 | true
126 | true
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
--------------------------------------------------------------------------------
/src/socket.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
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 |
--------------------------------------------------------------------------------
/src/socket.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------