完成端口服务端数据发送不出去!
天地大美 2008-02-17 10:30:07 我用iocp封装了一个类,做的服务器端,提供文件下载。
我是在线程里调用 wsasend发送的。
在本地测试,服务端工作良好可以提供下载文件。但放到远程服务器上时,就不能下载文件,数据发不出去。
排除服务器电脑和带宽问题。
下面是我封装的IOCP类,哪位大哥指示一下,不胜感激。
IOCPS.H
/////////////////
#include "../template/listtemplate.h" //自定义的链表模板类
#include "../template/hashlist.h" //自定义的HASH链表模板类
////////////////完成端口封装类/////////////////////////
#define IOCP_MAXBUFSIZE (4096+256) //最大缓冲区长度4K
#define CONNECT_TIMEOUT 20 //连接后多久没有收到数据自动断开(单位:秒)
typedef enum _IO_OPERATION
{
IOInitialize=100, // The client just connected
IOReadCompleted, // Read completed
IOWriteCompleted, // 发送完成一个
}IO_OPERATION, *PIO_OPERATION;
static GUID g_GUIDAcceptEx = WSAID_ACCEPTEX;
extern void ShowMsg(LPCSTR msg);
class CIOCPS
{
public:
class CClientContext
{
public:
WSAOVERLAPPED ol; //overlapped用于来回传递的没用的东西
IO_OPERATION IoOperation; //IO操作标志
SOCKET sClient; //套接字句柄
WSABUF wsaBuf; //
char Buf[IOCP_MAXBUFSIZE];//发送数据缓冲区
public:
CClientContext(IO_OPERATION iooper=IOInitialize,SOCKET s=INVALID_SOCKET,DWORD len=IOCP_MAXBUFSIZE)
{
IoOperation=iooper;
wsaBuf.buf=Buf;
wsaBuf.len=len;
sClient=s;
memset(&ol,0,sizeof(WSAOVERLAPPED));//必须初始化,否则在调用ACCEPTEX时出现错误代码6的错误
}
public:
void SetOperation(IO_OPERATION iooper){IoOperation=iooper;}
IO_OPERATION GetOperation(){return IoOperation;}
BOOL AddData(char *buf,int len)
{
if(len>IOCP_MAXBUFSIZE)
return FALSE;
memcpy(Buf,buf,len);
wsaBuf.buf=Buf;
wsaBuf.len=len;
return TRUE;
}
};
/////////////////////////////////////////////////////
class CClientSocket
{
public:
CListTemplate<CClientContext> ClientBuf;
SOCKET sClient; //套接字句柄
public:
CClientSocket()
{
sClient=INVALID_SOCKET;
}
~CClientSocket()
{
ClientBuf.DistoryList();
}
public:
CClientContext *AllocBuffer(IO_OPERATION io_oper,SOCKET s,DWORD datalen=IOCP_MAXBUFSIZE)
{
CClientContext newnode(io_oper,s,datalen);
return ClientBuf.AddNode(&newnode);
}
CClientContext *SafeAllocBuffer(IO_OPERATION io_oper,SOCKET s,DWORD datalen=IOCP_MAXBUFSIZE)
{//安全分配内存,如果超出范围则返回空,调和用者应该等待数据处理完毕再调用送
if(ClientBuf.GetCount()>6)//如果当前有太多未处理IO包,则返回空,
return NULL;
CClientContext newnode(io_oper,s,datalen);
return ClientBuf.AddNode(&newnode);
}
void ReleaseBuffer(CClientContext *pBuf)
{
if(pBuf==NULL)return;
POSITION pos=ClientBuf.GetFirstPosition();
CClientContext *pNode=NULL;
for(;pos!=NULL;)
{
pNode=ClientBuf.GetAt(pos);
if(pNode==pBuf)
{
ClientBuf.DelNode(pos);
return;
}
ClientBuf.MoveNext(pos);
}
ShowMsg("ReleaseBuffer Error");
}
};
///////////////////////////////////////////////////////////////
public:
HANDLE m_hIOCP;//完成端口句柄
SOCKET m_hListenSocket;//监听套接字句柄
HANDLE m_hAcceptEvent;//有需要接受连接的请求通知事件
LPFN_ACCEPTEX lpAcceptEx;
CRITICAL_SECTION m_AcceptClientListSection;//
CListTemplate<CClientSocket> m_AcceptClientList; //已经接受连接并且未收到数据的套接字链表
CHashList<CClientSocket> m_ClientList; //客户端链表
CRITICAL_SECTION m_ClientListSection;//
public:
DWORD m_dwListenThreadID; //
BOOL m_bShutDown;
HANDLE m_hListenThreadHandle;
DWORD m_dwWorkerThreadCount;
HANDLE *m_pWorkerThreadHandleArray;
public:
CIOCPS();
virtual ~CIOCPS();
public:
static UINT TF_QueryIoStatusThread(LPVOID lp);//循环调用GetQueuedCompletionStatus获取当前IO状态的线程
static UINT TF_ListenThread(LPVOID lp);//监听线程,用于接受客户端的连接请求
protected:
virtual void AppendLog(CString msg)
{ }
virtual void NotifyOnAccept(SOCKET s)
{ }
virtual void NotifyOnDisconnect(SOCKET s)
{ }
virtual void NotifyOnReceive(SOCKET s,char *buf,DWORD len)
{ }
virtual void NotifyOnSendComplete(SOCKET s)
{ }
private:
BOOL InitWinsock();
BOOL PostAcceptEx();
void ProcessIOMessage(IO_OPERATION IoOperation,CClientContext *pContext,DWORD dwIoSize);
CString ErrorCode2Text(DWORD dw);
void LockAcceptList();
void UnlockAcceptList();
void DelSocketOnAcceptList(SOCKET s);
void LockClientList();
void UnlockClientList();
private:
void OnReadCompleted(CClientSocket *pClient,CClientContext *pContext,DWORD dwIoSize);
void OnWrite(CClientSocket *pClient,CClientContext *pContext,DWORD dwIoSize);
void OnWriteCompleted(CClientSocket *pClient,CClientContext *pContext,DWORD dwIoSize);
public:
BOOL Startup(char *pListenIp,u_short uListenPort);
BOOL SendData(SOCKET s,char *buf,int len);
int SafeSendData(SOCKET s,char *buf,int len);
void ShutDown();
public:
void DisConnectClient(SOCKET s);
};
#endif // !defined(AFX_IOCPS_H__6F522E84_238B_4DC2_A27B_B415B99D3FA4__INCLUDED_)