提交 7f120ad8 编写于 作者: X xuchi

服务端和客户端IOCP网络模型支持IPV6

上级 c9d59a3b
......@@ -15,6 +15,7 @@
#include <stdio.h>
#include "Log.hpp" // 导入日志系统头文件
#include "NetWork.hpp"
#pragma comment(lib, "ws2_32.lib") // 添加windowsAPI-WSAStartup使用到了windows的一个静态链接库//注意:windows解决可以,为了实现跨平台可在项目属性配置里面配置这个静态库//
......@@ -127,7 +128,7 @@ namespace doyou {
}
// 向Iocp投递接收客户端连接的任务(异步操作)
bool PostAccept(IO_DATA_BASE* pIOData) // 错误返回机制先不用,但是可以先建立起来备用
bool PostAccept(IO_DATA_BASE* pIOData, int af) // 错误返回机制先不用,但是可以先建立起来备用
{
if (_lpfnAcceptEx == nullptr) { // 指针在使用前都应该进行判空安全校验
CELLLog_PError("PostAccept::_lpfnAcceptEx is null.");
......@@ -135,10 +136,20 @@ namespace doyou {
}
pIOData->iotype = IO_TYPE::ACCEPT; // 接收新客户端加入标识//指针变量间接访问对象
pIOData->sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // 提前创建好即将加入的新客户端套接字
SOCKET sock = socket(af, SOCK_STREAM, IPPROTO_TCP); // 提前创建好即将加入的新客户端套接字
if (INVALID_SOCKET == sock) { // 对创建socket套接字结果进行判断
CELLLog_PError("iocp PostAccept, create socket failed.");
}
else {
NetWork::make_reuseaddr(sock);
}
pIOData->sockfd = sock;
char buffer[1024] = {}; // 字符数组,并采用初始化器进行初始化,用来存储新加入客户端的IP地址和端口号等信息,也存在存储网络消息的场景等。
DWORD dwBytes = 0;
OVERLAPPED overLapped = {}; // 结构体初始化器,将结构体对象每个属性都置零了
int nAddrLen = (AF_INET6 == af ? sizeof(sockaddr_in6) : sizeof(sockaddr_in));
// 注意1:当para4传入大于0的数值时,就需要客户端connect发起连接,并发送一条网络消息send,iocp服务端才会正式的接受到新客户端加入的事件才算完成;para4-0时,客户端只需connect动作。
// 注意2:这是一个非阻塞函数(异步模式),(阻塞函数的话就是同步模式)
// 分析:向Iocp投递任务主体不是sockServer,而是sockClient相关信息
......@@ -149,8 +160,8 @@ namespace doyou {
pIOData->sockfd, // 新加入的客户端套接字
pIOData->wsabuff.buf, // 接收数据存储缓冲区
0, // 接收数据缓冲区大小 sizeof(buffer)-(sizeof(sockaddr_in)+16) * 2 0
sizeof(sockaddr_in) + 16, // 本端地址存储在buffer尾部位置,也就是在接受数据位置尾部开始存储这个本地地址
sizeof(sockaddr_in) + 16, // 远端地址存储在buffer尾部位置,也就是在接受数据位置尾部开始存储这个远端地址
nAddrLen + 16, // 本端地址存储在buffer尾部位置,也就是在接受数据位置尾部开始存储这个本地地址
nAddrLen + 16, // 远端地址存储在buffer尾部位置,也就是在接受数据位置尾部开始存储这个远端地址
NULL, // 实际接收到的数据的字节数据-&dwBytes
&pIOData->overLapped // 重叠体(类似并发概念,并不完全一致)
)) {
......
......@@ -41,7 +41,7 @@ namespace doyou {
IO_DATA_BASE ioData = {}; // 采用结构体的初始化器对结构体对象进行初始化
ioData.wsabuff.buf = buf;
ioData.wsabuff.len = len;
iocp.PostAccept(&ioData);
iocp.PostAccept(&ioData, _address_family); // 首次 向Iocp投递接收连接的任务
IO_EVENT ioEvent = {};
while (pThread->isRun())
......@@ -68,7 +68,7 @@ namespace doyou {
IocpAccept(ioEvent.pIOData->sockfd); // 客户端socket已知
// 待优化点:投递接收任务前,先校验已经连接的客户端总数是否超过连接上限
// 继续 向Iocp投递接收连接的任务
iocp.PostAccept(&ioData);
iocp.PostAccept(&ioData, _address_family);
}
} // while
......@@ -103,7 +103,8 @@ namespace doyou {
else {
// 获取IP地址 inet_ntoa(clientAddr.sin_addr)
// 分析:超出链接上限,先链接再关闭:
// 好处1)可以知道是谁链接我们了(客户端信息)。好处2)做一些其它操作,比如通知客户端我超限制了
// 好处1)可以知道是谁链接我们了(客户端信息)。
// 好处2)做一些其它操作,比如通知客户端我超限制了
// 好处3)可以查看该客户端是否在黑名单或白名单中,是否有传指定验证码token, 客户端需要传入一个正确的检验码。
// 如果重复多次链接,有可能是恶意链接。
NetWork::destroy_socket(cSock);
......
// 高性能服务器可采用的网络通信模型三选一:select/epoll/iocp/
#include "TcpSelectServer.hpp" // using select, both linux and windows.
//#include "TcpSelectServer.hpp" // using select, both linux and windows.
//#include "TcpEpollServer.hpp" // using epoll, only linux.
//#include "TcpIocpServer.hpp" // using iocp, only windows.
#include "TcpIocpServer.hpp" // using iocp, only windows.
#include "MsgStream.hpp"
#include "Config.hpp"
......@@ -11,7 +11,7 @@
using namespace doyou::io; // 使用名称空间
// 可使用服务模型(三选一):1-TcpSelectServer 2-TcpEpollServer 3-TcpIocpServer
class MyServer : public TcpSelectServer
class MyServer : public TcpIocpServer
{
public:
MyServer()
......
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{FF4CC1F1-6E8F-41D0-9D68-6F2FE967B93B}</ProjectGuid>
<RootNamespace>TestDemo</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="main.c" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="源文件">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="头文件">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="资源文件">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.c">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
</Project>
\ No newline at end of file
#pragma once
#pragma execution_character_set("utf-8")
#include <inaddr.h>
// SOCKET
#ifdef _WIN32
#define FD_SETSIZE 65535 // fd_set集合元素的最大值,集合中实际元素数量不能超过这个最大值
#define WIN32_LEAN_AND_MEAN
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <windows.h> // wins系统头文件
#include <WinSock2.h>
#include <ws2ipdef.h>
#include <WS2tcpip.h> // 系统库文件名不区分大小写
#pragma comment(lib,"ws2_32.lib")
#else
#ifdef __APPLE__
// 分析:通过查看macos系统API头文件中详细说明(这是最权威的说明,一般位API开发者提供的解释),只要定义了下面的宏,就解除了select网络模型对socket数量上限值的限定
#define _DARWIN_UNLIMITED_SELECT // 定义一个宏
#endif // !__APPLE__
#include<unistd.h> //uni std
#include<arpa/inet.h>
#include<string.h>
#include<signal.h>
#include<sys/socket.h>
#define SOCKET int
#define INVALID_SOCKET (SOCKET)(~0)
#define SOCKET_ERROR (-1)
#endif
void main()
{
struct in_addr inaddr;
char str[INET_ADDRSTRLEN];
memset(str, 0, INET_ADDRSTRLEN);
inaddr.s_addr = inet_addr("127.0.0.1"); // 假设in_addr为127.0.0.1
inet_ntop(AF_INET, &inaddr, str, INET_ADDRSTRLEN);
printf("TEST IP address is %s\n", str); // 输出IP地址
}
\ No newline at end of file
......@@ -14,6 +14,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Doc", "Doc", "{65CA60CF-E55
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Engine1.0", "Engine1.0\Engine1.0.vcxproj", "{0B0CA0D9-B821-407F-9772-D0AAB4A7E785}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestDemo", "TestDemo\TestDemo.vcxproj", "{FF4CC1F1-6E8F-41D0-9D68-6F2FE967B93B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
......@@ -32,6 +34,10 @@ Global
{0B0CA0D9-B821-407F-9772-D0AAB4A7E785}.Debug|Win32.Build.0 = Debug|Win32
{0B0CA0D9-B821-407F-9772-D0AAB4A7E785}.Release|Win32.ActiveCfg = Release|Win32
{0B0CA0D9-B821-407F-9772-D0AAB4A7E785}.Release|Win32.Build.0 = Release|Win32
{FF4CC1F1-6E8F-41D0-9D68-6F2FE967B93B}.Debug|Win32.ActiveCfg = Debug|Win32
{FF4CC1F1-6E8F-41D0-9D68-6F2FE967B93B}.Debug|Win32.Build.0 = Debug|Win32
{FF4CC1F1-6E8F-41D0-9D68-6F2FE967B93B}.Release|Win32.ActiveCfg = Release|Win32
{FF4CC1F1-6E8F-41D0-9D68-6F2FE967B93B}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册