异步非阻塞模式WSAAnyscSelect()模型的一连多的问题;

treamboy 2004-06-28 02:14:20
//.h文件的声明
SOCKET ServerSock;
SOCKET ClientSock[10]; //存储与客户端通信的Socket的数组
void InsertStringToListbox(char *strdisp);
void OnClose(SOCKET CurSock); //对端Socket断开
void OnSend(SOCKET CurSock); //发送网络数据包
void OnReceive(SOCKET CurSock); //网络数据包到达
void OnAccept(SOCKET CurSock); //客户端连接请求

BOOL InitNetwork(); //初始化网络函数
void OnNetEvent(WPARAM wParam, LPARAM lParam); //异步事件回调函数

int iport;
-----------------------------------------------------------------------
BOOL CTestSnycSelectDlg::InitNetwork()
{
WSADATA wsaData;
BOOL ret = WSAStartup(MAKEWORD(2,2), &wsaData);
if(ret != 0)
{
InsertStringToListbox("初始化网络协议失败!");
return FALSE;
}
else
{
InsertStringToListbox("初始化网络协议success!");
}
ServerSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(ServerSock == INVALID_SOCKET)
{
InsertStringToListbox("创建套接字失败!");
closesocket(ServerSock);
WSACleanup();
return FALSE;
}
else
{
InsertStringToListbox("创建套接字success!");
}
sockaddr_in localaddr;
localaddr.sin_family = AF_INET;
iport = 3000;
localaddr.sin_port = htons(iport); //端口号不要与其他应用程序冲突
//localaddr.sin_addr.s_addr = 0;
localaddr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(ServerSock ,(struct sockaddr*)&localaddr,sizeof(sockaddr))
== SOCKET_ERROR)
{
InsertStringToListbox("绑定地址失败!");
closesocket(ServerSock);
WSACleanup();
return FALSE;
}
else
{
InsertStringToListbox("绑定地址success!");
}
if(WSAAsyncSelect(ServerSock, m_hWnd, NETWORK_EVENT,
FD_ACCEPT | FD_CLOSE | FD_READ | FD_WRITE) == SOCKET_ERROR)
{
InsertStringToListbox("注册网络异步事件失败!");
WSACleanup();
return FALSE;
}
else
{
InsertStringToListbox("注册网络异步事件success!");
}
listen(ServerSock, 5); //设置侦听模式
return TRUE;
}
void CTestSnycSelectDlg::OnNetEvent(WPARAM wParam, LPARAM lParam)
{
//调用Winsock API函数,得到网络事件类型
int iEvent = WSAGETSELECTEVENT(lParam);

//调用Winsock API函数,得到发生此事件的客户端套接字
SOCKET CurSock= (SOCKET)wParam;

switch(iEvent)
{
case FD_ACCEPT: //客户端连接请求事件
OnAccept(CurSock);
break;
case FD_CLOSE: //客户端断开事件:
OnClose(CurSock);
break;
case FD_READ: //网络数据包到达事件
OnReceive(CurSock);
break;
case FD_WRITE: //发送网络数据事件
OnSend(CurSock);
break;
default: break;
}
}

void CTestSnycSelectDlg::OnAccept(SOCKET CurSock)
{
//接受连接请求,并保存与发起连接请求的客户端进行通信Socket
//为新的socket注册异步事件,注意没有Accept事件
for(int i = 0;i < 10;i++ )
{
if(ClientSock[i] == 0)
{
ClientSock[i] = accept(CurSock,NULL,NULL);
break;
}

}
WSAAsyncSelect(ClientSock[i],m_hWnd,NETWORK_EVENT,FD_WRITE|FD_CLOSE);
InsertStringToListbox("accept the data!");
}

void CTestSnycSelectDlg::OnClose(SOCKET CurSock)
{
//结束与相应的客户端的通信,释放相应资源
for(int i = 0;i < 10;i++ )
{
if(ClientSock[i] == CurSock)
{
closesocket(CurSock);
WSACleanup();
break;
}

}

InsertStringToListbox("close the socket!");
}

void CTestSnycSelectDlg::OnSend(SOCKET CurSock)
{
//在给客户端发数据时做相关预处理
int rc;
char Buffer[100] = "OnSend";
for(int i = 0;i < 10;i++ )
{
if(ClientSock[i] == CurSock)
{
rc = send(ClientSock[i],Buffer,sizeof(Buffer), 0);
break;
}

}

if (rc == SOCKET_ERROR) {
InsertStringToListbox("send出错!");

}
if (rc ==0) {
InsertStringToListbox("send正确!");
}
}

void CTestSnycSelectDlg::OnReceive(SOCKET CurSock)
{
//读出网络缓冲区中的数据包
char Buffer[100];
int rc;
for(int i = 0;i < 10;i++ )
{
if(ClientSock[i] == CurSock)
{
rc = recv(CurSock,Buffer,sizeof(Buffer),0);
break;
}

}

if (rc == SOCKET_ERROR) {
InsertStringToListbox("Recv出错!");

}
if (rc ==0) {
InsertStringToListbox("Recv正确!");
}
}
//为什么我只能连接一个客户端????错在哪里?
...全文
205 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
treamboy 2004-06-29
  • 打赏
  • 举报
回复
哈哈,谢谢各位。
误导各位了,程序没错,是我自己的提示信息错了。
但各位给的信息对我很有帮助,再谢了。: )
PiggyXP 2004-06-28
  • 打赏
  • 举报
回复
楼主的代码太长了,看得都眼花了,我觉得先像 piaorenqian(湖心孤舟)说得那样,

在rc = recv(ClientSock[i],Buffer,sizeof(Buffer)后面加上
DWORD dwError = WsaGetLastError();
看看dwError是多少

知道了错误号,好做诊断呵呵^_^
自由的风 2004-06-28
  • 打赏
  • 举报
回复
setsockopt(...SO_REUSEADDR...)

既然没加,为什么不加上看看?
piaorenqian 2004-06-28
  • 打赏
  • 举报
回复
在rc = recv(ClientSock[i],Buffer,sizeof(Buffer)后面加上
DWORD dwError = WsaGetLastError();
看看dwError是多少
treamboy 2004-06-28
  • 打赏
  • 举报
回复
rc = recv(ClientSock[i],Buffer,sizeof(Buffer),0);//此步有错误。
rc跟踪结果是 -1
treamboy 2004-06-28
  • 打赏
  • 举报
回复
setsockopt(...SO_REUSEADDR...)没有?
//----------没有:(
要不你先把这个socket数组里面的值都初始化为0试试看?
//----------也还是不行:(
treamboy 2004-06-28
  • 打赏
  • 举报
回复
再看了下
void CTestSnycSelectDlg::OnAccept(SOCKET CurSock)
{
SOCKET Sclient;
//接受连接请求,并保存与发起连接请求的客户端进行通信Socket
//为新的socket注册异步事件,注意没有Accept事件
for(int i = 0;i< 5;i++ )
{
// ClientSock[i] = 0;
if(ClientSock[i] == 0)
{
ClientSock[i] = accept(ServerSock,NULL,NULL);
Sclient = ClientSock[i];
TRACE("trace the ClientSock[i]\n");
break;
}
}
if (Sclient == NULL) {
InsertStringToListbox("accept出错!");
}
else
{
InsertStringToListbox("accept正确!");
}
WSAAsyncSelect(ClientSock[i],m_hWnd,NETWORK_EVENT,FD_WRITE|FD_CLOSE);

}//--------------这个是对的,跟踪完全正确

void CTestSnycSelectDlg::OnReceive(SOCKET CurSock)
{
//读出网络缓冲区中的数据包
char Buffer[100];
int rc;

for(int i = 0;i< 5;i++ )
{
if(ClientSock[i] == CurSock)
{
rc = recv(ClientSock[i],Buffer,sizeof(Buffer),0);//此步有错误。
break;
}

}
if (rc == SOCKET_ERROR) {
InsertStringToListbox("Recv出错!");

}

if (rc ==0) {
InsertStringToListbox("Recv正确!");
}
}
自由的风 2004-06-28
  • 打赏
  • 举报
回复
粗看了一下
你用了setsockopt(...SO_REUSEADDR...)没有?
PiggyXP 2004-06-28
  • 打赏
  • 举报
回复
那楼主说的不行了,具体错误是什么呢?
treamboy 2004-06-28
  • 打赏
  • 举报
回复
ciqi1979@hotmail.com
treamboy 2004-06-28
  • 打赏
  • 举报
回复
第一次做SOCKET
MFCClass(profan) 你能把你的代码给我看看么?如果方便的话,就谢谢了,如果不方便那就大家帮我找错吧,嘿嘿。
MFCClass 2004-06-28
  • 打赏
  • 举报
回复
当然可以了
treamboy 2004-06-28
  • 打赏
  • 举报
回复
listen(ServerSock, 5); //设置侦听模式
这个是没错的, listen的默认值就是5啊。
最后我设置SOCKET ClientSock[10]; //存储与客户端通信的Socket的数组
当我这个 server是初次运行时我从客户端只开两个 client 不就行了,那就没超过 5了
PiggyXP 2004-06-28
  • 打赏
  • 举报
回复
ClientSock[i]

要不你先把这个socket数组里面的值都初始化为0试试看?

应该可以了吧?
PiggyXP 2004-06-28
  • 打赏
  • 举报
回复
listen(ServerSock, 5); //设置侦听模式

不可能啊,可以连接的客户多少就是这个参数设置的,既然你设置的是5,那就是可以同时处理5个连接

也许是错在别的地方了^_^
treamboy 2004-06-28
  • 打赏
  • 举报
回复
to:MFCClass(profan)
对,我是这样想的。
你的连上多个可以么???
MFCClass 2004-06-28
  • 打赏
  • 举报
回复
void CTestSnycSelectDlg::OnAccept(SOCKET CurSock)
{
//接受连接请求,并保存与发起连接请求的客户端进行通信Socket
//为新的socket注册异步事件,注意没有Accept事件
for(int i = 0;i < 10;i++ )
{
if(ClientSock[i] == 0)
{
ClientSock[i] = accept(CurSock,NULL,NULL);
break;
}

}
WSAAsyncSelect(ClientSock[i],m_hWnd,NETWORK_EVENT,FD_WRITE|FD_CLOSE);
InsertStringToListbox("accept the data!");
}
你这段我理解的意思是,你循环的判断这个叔祖,那个是空闲的,然后就将其副值新接受的客户连接,然后就设置这个client socket 的io模型是wsaasyncselect(),
我没有这样做过,我是定义一个全局的变量记录连接的数量。

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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