RakNet V2.454中对完成端口的修复

RakNet 2.454版本的完成端口功能存在缺陷,主要原因是套接字绑定时机不当和重复捆绑。通过调整绑定时机并调用特定函数SetupIOCompletionPortSocket,可以在服务器端解决此问题,允许更多客户端连接。已提供修复后的源代码下载链接。
摘要由CSDN通过智能技术生成

    RakNet是RakkarSoft的一个网络引擎(http://www.rakkarsoft.com/) 。该引擎有商业版和非商业版之分,非商业版意味着免费,同时也意味着代码质量不会很高,因为它不可能傻到把免费版做来比商业版要好。虽然2.454版本的文档明确了可以使用完成端口(注意:RakNet后续版本都不再支持完成端口),但是在实际代码中,完成端口部分的代码却不能工作。由于项目需要,我对其进行了修复。

    下面是在修改过程中对RakNet连接过程及错误的简要分析:

    下图展示了利用RakNet提供的C/S聊天程序进行连接的过程。无论是否采用完成端口,该过程都是相同的。

    下图为状态转换图,清晰地显示了创建连接的全过程。

RakNet 2.454版本中,完成端口不能正常工作主要原因如下:

1、  将加密套接字与完成端口绑定的时机不对。从连接图我们可以看出客户端最好的时机是在客户端收到ID_CONNECTION_REQUEST_ACCEPTED,服务器最好的时机为在收到ID_NEW_INCOMING_CONNECTION的时候。

2、 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
国人开发强悍IOCP代码,全部代码 其一个单元的代码: unit uIOCompletionPort; interface uses Windows, WinSock2, uWin32Const, uException, uDIProtocol, uDIClientChannel; type TIOCompletionPort = class private m_hCompletionPort: Thandle; private procedure CreateCompletionPort; public function AssociateSocketWithCompletionPort( hDevice: THandle; dwCompletionKey: DWORD): Boolean; function GetIOCompletionStatus( var FClientChannel: TDIClientChannel; var pHandleData: PPerHandleData; var dwIoSize: DWORD): Boolean; overload; function GetIOCompletionStatus( var FClientChannel: TDIClientChannel; var pHandleData: PPerHandleData; var dwIoSize: DWORD; dwMilliseconds: DWORD): Boolean; overload; function PostIOCompletionStatus( lpCompletionKey: DWORD; lpOverlapped: POverlapped; lpNumberOfBytesTransferred: DWORD): Boolean; public constructor Create; destructor Destroy; override; end; implementation constructor TIOCompletionPort.Create; begin inherited Create; CreateCompletionPort; end; destructor TIOCompletionPort.Destroy; begin CloseHandle(m_hCompletionPort); inherited Destroy; end; procedure TIOCompletionPort.CreateCompletionPort; var s: TSocket; begin s := Winsock2.socket(AF_INET, SOCK_STREAM, IPPROTO_IP); if (s = Winsock2.INVALID_SOCKET) then raise TException.Create(ErrWin32Error, GetLastError(), 'Winsock2.socket'); m_hCompletionPort := CreateIOCompletionPort(s, 0, 0, 0); if (m_hCompletionPort = 0) then raise TException.Create(ErrWin32Error, GetLastError(), 'CreateIOCompletionPort'); Winsock2.closesocket(s); end; function TIOCompletionPort.AssociateSocketWithCompletionPort( hDevice: THandle; dwCompletionKey: DWORD ): Boolean; var h: THandle; begin Result := TRUE; h := CreateIOCompletionPort(hDevice, m_hCompletionPort, dwCompletionKey, 0); if (h m_hCompletionPort) then begin Result := FALSE; raise TException.Create(ErrWin32Error, GetLastError(), 'AssociateSocketWithCompletionPort'); end; end; function TIOCompletionPort.GetIOCompletionStatus( var FClientChannel: TDIClientChannel; var pHandleData: PPerHandleData; var dwIoSize: DWORD): Boolean; begin Result := GetQueuedCompletionStatus( m_hCompletionPort, dwIOSize, DWORD(FClientChannel), POVERLAPPED(pHandleData), INFINITE ); end; function TIOCompletionPort.GetIOCompletionStatus( var FClientChannel: TDIClientChannel; var pHandleData: PPerHandleData; var dwIoSize: DWORD; dwMilliseconds: DWORD): Boolean; var bRet: Boolean; nLastError: DWORD; begin bRet := TRUE; if FALSE = GetQueuedCompletionStatus( m_hCompletionPort, dwIOSize, DWORD(FClientChannel), POVERLAPPED(pHandleData), INFINITE ) then begin nLastError := GetLastError(); if (nLastError WAIT_TIMEOUT) then raise TException.Create(ErrWin32Error, GetLastError(), 'GetQueuedCompletionStatus'); bRet := FALSE; end; Result := bRet; end; function TIOCompletionPort.PostIOCompletionStatus( lpCompletionKey: DWORD; lpOverlapped: POverlapped; lpNumberOfBytesTransferred: DWORD): Boolean; begin Result := PostQueuedCompletionStatus( m_hCompletionPort, lpNumberOfBytesTransferred, lpCompletionKey, lpOverlapped ); end; end.
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值