网络编程-完成端口-服务器给客户端发消息服务器收到了的问题

wl_04_22_ 2012-05-09 11:35:49
先说问题在附上源代码:

我服务器在没做发送之前,就是只能接收,完全没任何问题,
我开了20个client给svr发消息都没问题,都能收到,客户端只能发送哪种。
但是当我做了相互后,就是服务器和客户端可以互发消息互相接收消息后,
客户端打开连接正常,发送第一条消息正常,

接下来,服务器给客户端发的消息 客户端貌似都收到了,
但是客户端给服务器发的消息 服务器再也收不到了,
并且,服务器给客户端发的消息 服务器收到了,
这就不对了,对不...

服务器给客户端发的消息 服务器怎么能收到。。。
我这些代码vs10和vs03都能编译通过。

代码里有一点需要说明的是:
服务器创建的2个套接字和客户端连接的套接字的存放形式不一样,
服务器创建的2个套接字是用链表形式存的。
客户端连接的套接字是存在哈希表里的。

希望各位大侠能帮帮我,我整了2晚上,问了1天,实在是无能为力了。谢谢




--------------------------
#include "cCompletePort.h"


int main(int _Argc, char **_argv)
{
WSADATA wsadt;

if(WSAStartup(MAKEWORD(2,2),&wsadt) != 0)
{
assert(0);
return -1;
}

cCompletePort test;
test.WaitThreadWork();

WSACleanup();
system("pause");
return 0;
}



由于篇幅过长
我在百度空间里写了这个,
也就是剩下的一部分代码
csdn博客3天内不允许我发文章...
http://hi.baidu.com/wangli071229/blog/item/d38167ef1c75cd16acafd5ae.html
...全文
202 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
stjay 2012-05-10
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 的回复:]

太长,没仔细看
关键是每次PostRecv、PostSend要用不同的PERIODATA
不要同时使用一个PERIODATA,要每次新建一个
也就是LPWSAOVERLAPPED这个参数不要共用
C/C++ code
typedef struct sPerHandleData
{
PERIODATA sPerIOData; //这样定义就只能进行一次IO操作,要等……
[/Quote]

或者试试在sPerHandleData里用2个PERIODATA,1个PostRecv,1个PostSend
如果想多收多发,还是每次新建一个PERIODATA吧
stjay 2012-05-10
  • 打赏
  • 举报
回复
太长,没仔细看
关键是每次PostRecv、PostSend要用不同的PERIODATA
不要同时使用一个PERIODATA,要每次新建一个
也就是LPWSAOVERLAPPED这个参数不要共用
typedef struct sPerHandleData
{
PERIODATA sPerIOData; //这样定义就只能进行一次IO操作,要等IO完成才能次下一次操作,最好独立出来
SOCKET sSvrSkt;
....
}
zhanshen2891 2012-05-10
  • 打赏
  • 举报
回复
不是想打击你,基础不行就不要强求了,你说的这些问题是基本的不能再基本的问题了。能出这些问题说明你的基础实在太差了,还不到可以写网络程序的程度。

你需要先积累一些编程经验,然后再学习一下网络原理。再写这样的程序就会很容易的,出了问题自己也能很容易解决。
wl_04_22_ 2012-05-10
  • 打赏
  • 举报
回复
谢谢 stjay
能不能加QQ讨论下呢,我QQ 779400776

对于zhanshen2891,也谢谢你吧,
不过请你在给出具体的回答后,给点建议,
wl_04_22_ 2012-05-09
  • 打赏
  • 举报
回复
下来2个回复是一个文件的代码,只是太长了,超过了1w字符

#include "cCompletePort.h"

#include "H:\CODE\common\net\net.h"

cCompletePort::cCompletePort(void)
{
mp_head = NULL;
m_hCompletionPort = NULL;
memset(m_hthread,0,sizeof(HANDLE) * MAX_THREAD_COUNT);
m_threadCount = 0;
m_perHandleDataSvrCount = 0;

if( !Init(PORT) )
{
printf("init() err.\n");
return;
}
}


cCompletePort::~cCompletePort(void)
{
if(m_hCompletionPort != NULL)
{
SAFE_CLOSEHANDLE(m_hCompletionPort);
}

for (int i = 0; i < m_threadCount; ++i)
{
SAFE_CLOSEHANDLE(m_hthread[i]);
}

PPERHANDLEDATA tmp_crt = mp_head,
tmp_nxt= mp_head;
do
{
tmp_nxt = tmp_nxt->next;
SAFE_CLODESOCKET(tmp_crt->sPerIOData.sCltSkt);
SAFE_CLODESOCKET(tmp_crt->sSvrSkt);
SAFE_DELETE(tmp_crt);
tmp_crt = tmp_nxt;

} while (tmp_crt != NULL);

tPerIOMapMap::iterator be = m_PerIOMapMap.begin();
PPERHANDLEDATA tmp_perHandleData = NULL;
while(be != m_PerIOMapMap.end())
{
tmp_perHandleData = (be++)->second;
if(tmp_perHandleData != NULL)
{
m_PerIOMapMap.erase(tmp_perHandleData->sPerIOData.sCltSkt);
SAFE_CLODESOCKET(tmp_perHandleData->sPerIOData.sCltSkt);
SAFE_DELETE(tmp_perHandleData);
}
}
m_PerIOMapMap.clear();
}

bool cCompletePort::Init( DWORD port, char *addr /*= NULL*/ )
{
int err = 0;

m_hCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);
if(m_hCompletionPort == NULL)
{
printf("CreateIoCompletionPort() err [%d].\n",err = WSAGetLastError());
assert(0);
return FALSE;
}

SYSTEM_INFO si;
GetSystemInfo(&si);
for (m_threadCount = 0; m_threadCount < 1/*si.dwNumberOfProcessors*//* * 2*/; ++m_threadCount)
{
m_hthread[m_threadCount] = (HANDLE)_beginthreadex(NULL,0,WorkThread,(PVOID)this,0,0);
if(m_hthread[m_threadCount] == NULL)
{
printf("_beginthreadex() err [%d].\n",GetLastError());
assert(0);
return false;
}
}

char szPort[5];
wsprintf(szPort,"%d",port);
struct addrinfo *res = ResolveAddress(AF_INET,SOCK_STREAM,IPPROTO_TCP,addr,szPort);
if(res == NULL)
{
printf("ResolveAddress() err.\n");
assert(0);
return false;
}
struct addrinfo *tmp_res = res;
while(tmp_res != NULL)
{
PPERHANDLEDATA tmp_svr = AllocPerHandleDataSvr();
if(tmp_svr == NULL)
{
assert(0);
return false;
}

tmp_svr->sAf = tmp_res->ai_family;
tmp_svr->sSockType = tmp_res->ai_socktype;
tmp_svr->sProtocol = tmp_res->ai_protocol;
tmp_svr->sSvrSkt = WSASocket(tmp_svr->sAf,tmp_svr->sSockType,tmp_svr->sProtocol,
0,0,WSA_FLAG_OVERLAPPED);
if(tmp_svr->sSvrSkt == INVALID_SOCKET)
{
printf("WSASocket() err [%d].\n",WSAGetLastError());
assert(0);
return false;
}

if( !Initlpfn( tmp_svr ) )
{
assert(0);
return false;
}

if(CreateIoCompletionPort((HANDLE)tmp_svr->sSvrSkt,
m_hCompletionPort,(ULONG_PTR)tmp_svr,0) == NULL)
{
printf("socket with CreateIoCompletionPort() err [%d].\n",WSAGetLastError());
assert(0);
return false;
}

memcpy( &tmp_svr->sPerIOData.sAddr,tmp_res->ai_addr,tmp_res->ai_addrlen);
tmp_svr->sPerIOData.sAddr_size = tmp_res->ai_addrlen;
err = bind(tmp_svr->sSvrSkt,(SOCKADDR*)&tmp_svr->sPerIOData.sAddr,
tmp_svr->sPerIOData.sAddr_size);
if(err == SOCKET_ERROR)
{
printf("bind() err [%d].\n",WSAGetLastError());
assert(0);
return false;
}

err = listen(tmp_svr->sSvrSkt,100);
if(err == SOCKET_ERROR)
{
printf("listen() err [%d].\n",WSAGetLastError());
assert(0);
return false;
}

if( !PostAcceptEx(tmp_svr) )
{
assert(0);
return false;
}

tmp_res = tmp_res->ai_next;
}

FreeAddrInfo(res);


return true;
}

bool cCompletePort::Initlpfn( PPERHANDLEDATA tmp_svr )
{
if(tmp_svr == NULL)
{
assert(0);
return false;
}

if(mp_head->next != NULL)
{
tmp_svr->slpfnAcceptEx = mp_head->next->slpfnAcceptEx;
tmp_svr->slpfnGetAcceptExSockaddrs = mp_head->next->slpfnGetAcceptExSockaddrs;
return true;
}

GUID guidAcceptEx = WSAID_ACCEPTEX;
DWORD bytes;
int rc = 0;

rc = WSAIoctl(
tmp_svr->sSvrSkt,
SIO_GET_EXTENSION_FUNCTION_POINTER,
&guidAcceptEx,
sizeof(guidAcceptEx),
&tmp_svr->slpfnAcceptEx,
sizeof(tmp_svr->slpfnAcceptEx),
&bytes,
NULL,
NULL
);
if (rc == SOCKET_ERROR)
{
fprintf(stderr, "WSAIoctl: SIO_GET_EXTENSION_FUNCTION_POINTER failed: %d\n",
WSAGetLastError());
return false;
}

GUID guidGetAcceptExSockaddrs = WSAID_GETACCEPTEXSOCKADDRS;
rc = WSAIoctl(
tmp_svr->sSvrSkt,
SIO_GET_EXTENSION_FUNCTION_POINTER,
&guidGetAcceptExSockaddrs,
sizeof(guidGetAcceptExSockaddrs),
&tmp_svr->slpfnGetAcceptExSockaddrs,
sizeof(tmp_svr->slpfnGetAcceptExSockaddrs),
&bytes,
NULL,
NULL
);
if (rc == SOCKET_ERROR)
{
fprintf(stderr, "WSAIoctl: SIO_GET_EXTENSION_FUNCTION_POINTER faled: %d\n",
WSAGetLastError());
return false;
}

return true;
}

UINT WINAPI cCompletePort::WorkThread( PVOID lparam )
{
cCompletePort *pCp = (cCompletePort *)lparam;
pCp->BatchComplete();

return 0;
}



wl_04_22_ 2012-05-09
  • 打赏
  • 举报
回复

/***********************************************************************
作者: 王利
时间: 2012年5月6日21:18:09
修改时间: 2012年5月6日21:18:17
版本: 1.0
文件: cCompletePort.h
cCompletePort.cpp
H:\CODE\common\net\stdafx.h
H:\CODE\common\net\net.h
chat_svr.cpp
说明: 完成端口的示例代码
***********************************************************************/

#pragma once

#include "H:\CODE\common\net\stdafx.h"

const UINT MAX_THREAD_COUNT = 16;

#define QUIT_THREAD "quit"

enum eOperatorType
{
eOT_NONE = 0,
eOT_READ,
eOT_WRITE,
eOT_ACCEPT,
eOT_CLOSED,
eOT_END,
eOT_ERR,

eOT_MAX,
};

class cRAII_CriticalSection
{
public:
cRAII_CriticalSection(CRITICAL_SECTION *cs)
{
mp_cs = cs;
EnterCriticalSection(mp_cs);
}
~cRAII_CriticalSection()
{
LeaveCriticalSection(mp_cs);
}
private:
CRITICAL_SECTION *mp_cs;
};

typedef struct sPerIOData
{
WSAOVERLAPPED sOverlapped;
char sBuffer[BUFFER_SIZE];
DWORD sBuffer_size;
eOperatorType sOt;
SOCKET sCltSkt;
DWORD sAddr_size;
SOCKADDR_STORAGE sAddr;
CRITICAL_SECTION sSockCritSec;
}PERIODATA,*PPERIODATA;

typedef struct sPerHandleData
{
PERIODATA sPerIOData;
SOCKET sSvrSkt;
int sAf;
int sSockType;
int sProtocol;

LPFN_ACCEPTEX slpfnAcceptEx;
LPFN_GETACCEPTEXSOCKADDRS slpfnGetAcceptExSockaddrs;

struct sPerHandleData *next;

sPerHandleData(void)
{
slpfnAcceptEx = NULL;
slpfnGetAcceptExSockaddrs = NULL;
next = NULL;
}
}PERHANDLEDATA,*PPERHANDLEDATA;

class cCompletePort
{
public:
cCompletePort(void);
~cCompletePort(void);

public:
bool Init(DWORD port, char *addr = NULL);
void WaitThreadWork();
bool PostSend(PPERHANDLEDATA tmp_clt);

// 以下所有不是给你调用的,就是说 不是开放接口,不要在其他的类或者代码里使用以下所有
public:
void BatchComplete();

public:
static UINT WINAPI WorkThread(PVOID lparam);

private:
PPERHANDLEDATA AllocPerHandleDataSvr(void);
PPERHANDLEDATA AllocPerHandleDataClt(PPERHANDLEDATA tmp_svr);
bool ErasePerHandleData(SOCKET s);
bool Initlpfn(PPERHANDLEDATA tmp_svr);
bool PostAcceptEx(PPERHANDLEDATA tmp_svr);
bool AcceptComplete(PPERHANDLEDATA tmp_svr,PPERIODATA tmp_iodata);
bool PostRecv(PPERHANDLEDATA tmp_clt);
void PrintAcceptAddr(PPERHANDLEDATA tmp_clt);
void MsgDoPocessCenter(PPERIODATA tmp_iodata);
bool EndThread(PPERIODATA tmp_iodata);
bool SendComplete(PPERHANDLEDATA tmp_clt);

private:
PPERHANDLEDATA mp_head;
int m_perHandleDataSvrCount;

HANDLE m_hCompletionPort;

HANDLE m_hthread[MAX_THREAD_COUNT];
int m_threadCount;

typedef hash_map<SOCKET,PPERHANDLEDATA> tPerIOMapMap;
tPerIOMapMap m_PerIOMapMap;
};



wl_04_22_ 2012-05-09
  • 打赏
  • 举报
回复
在这里我发剩下的代码吧,我没注意回复有1w个字符


下面是客户端的代码,简短,先上

#include "..\..\..\..\..\common\net\net.h"

int main(int argc, char **argv)
{
//if(argc <= 1)
//{
// printf("parameter is not enough.");
// return false;
//}

WSADATA wsadata = {0};

SOCKET SKT_send = 0;
SOCKADDR_IN SKD_addr;
int ret = 0;

if ((ret = WSAStartup(MAKEWORD(2,2), &wsadata)) != 0)
{
assert(0);
return false;
}

if((SKT_send = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) == INVALID_SOCKET)
{
assert(0);
WSACleanup();
return false;
}

LookSvr(&SKD_addr);
SKD_addr.sin_port = htons(PORT);

char connect_count = 0;
const char connect_count_max = 3;
printf("连接中...\n");
while(connect_count < connect_count_max)
{
if(connect(SKT_send,(SOCKADDR *)&SKD_addr,sizeof(SKD_addr)) == SOCKET_ERROR)
{
++connect_count;
continue;
}
else
break;
}

if(connect_count < connect_count_max)
{
const unsigned int buffer_size = 2048;
char buffer[2048] = {0};

printf("连接成功,你可以输入数据...\n");
while(true)
{
cin.getline(buffer,buffer_size);
if(strlen(buffer) <= 0)
{
cin.clear();
buffer[0] = 0;
continue;
}

ret = send(SKT_send,buffer,buffer_size,0);
if(ret == SOCKET_ERROR)
{
printf("send err: %s\n",buffer);
assert(0);
}

memset(buffer,0,buffer_size);

ret = recv(SKT_send,buffer,buffer_size,0);
if(ret == SOCKET_ERROR)
{
printf("send err: %s\n",buffer);
assert(0);
}
else
{
printf("RECV:\t[%d]\t%s\n",strlen(buffer),buffer);
}

cin.clear();
buffer[0] = 0;
}
}
else
{
printf("连接超时,错误代码 [%d].\n",WSAGetLastError());
}

closesocket(SKT_send);
WSACleanup();
system("pause");
return 0;
}

65,210

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧