├── 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函数,大概长这个样子:![](./image/Async.jpg) 146 | - 其中最重要的函数是SockCheckAndInitAsyncSelectHelper:![](./image/complet.jpg) 147 | - SockCheckAndInitAsyncSelectHelper函数先创建了一个\\Device\\Afd\\AsyncSelectHlp的IO(功能未知),**然后用SockCreateAsyncQueuePort函数创建了一个完成端口** 148 | - 接着用NtSetInformationFile函数将完成端口和\\Device\\Afd\\AsyncSelectHlp绑定。 149 | - 在SockAsyncSelectCompletion函数中找到SockProcessAsyncSelect:![](./image/SockAsyncSelectCompletion.png) 150 | - 在SockProcessAsyncSelect中找到AsyncSelect真正实现原理:![](./image/SockProcessAsyncSelect.png) 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`测试:![](./image/Client.gif) 294 | - Server端1000连接测试:![](./image/Server.gif) 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 | --------------------------------------------------------------------------------