我这Socket Select逻辑有没有错?

gxx2019 2009-09-08 10:21:40
服务器端:

DWORD WINAPI CDisComSrvDlg::RecBusyOrNot(LPVOID lpParameter)
{
CDisComSrvDlg* pServe = (CDisComSrvDlg*)lpParameter;
SOCKET sListen = pServe->GetSockSrv();

FD_SET allSockfd; //服务器所有套接字结合
FD_ZERO(&allSockfd); //清空集合
FD_SET (sListen, &allSockfd); //将监听套接字加入该集合

FD_SET readfd; //定义满足可读套接字
FD_SET writefd; //定义满足可写套接字

while (pServe->IsConnenting()) //服务器运行
{
FD_ZERO(&readfd); //清空
FD_ZERO(&writefd);
readfd = allSockfd; //赋值
writefd = allSockfd;
//更新界面
pServe->ShowClientNumberInfor(allSockfd.fd_count);
//无限期等待套接字满足条件
int nRet = select(0, &readfd, &writefd, NULL, NULL);
if (nRet > 0)
{
//遍历所有套接字集合
for (int i = 0; i < allSockfd.fd_count; i++)
{
//存在可读的套接字
if (FD_ISSET(allSockfd.fd_array[i], &readfd))
{
//连接服务器请求的套接字
if (allSockfd.fd_array[i] == sListen)
{
SOCKADDR_IN addrClient;
int naddrLen = sizeof(addrClient);
SOCKET sClient = accept(sListen, (sockaddr*)&addrClient, &naddrLen);
//加入套接字
FD_SET(sClient, &allSockfd);
pServe->ShowClientNumberInfor(allSockfd.fd_count);
//处理
pServe->EstiClientState(addrClient);
pServe->AllotWork(sClient, addrClient);
}
else //接收客户端的数据
{
SOCKET sRecv = allSockfd.fd_array[i]; //获取套接字
BOOL nRet = pServe->ReadClientData(sRecv);
if (nRet == FALSE) //失败
{
FD_CLR(allSockfd.fd_array[i], &allSockfd); //清除
pServe->ShowClientNumberInfor(allSockfd.fd_count);
}
}
}//if
//可写的套接字
if (FD_ISSET(allSockfd.fd_array[i], &writefd))
{
//已处理
}
}
}
Sleep(THREAD_SLEEP);
}
return 0;
}
客户端代码:

DWORD WINAPI CEdisComClientDlg::RecvAndSend(LPVOID lpParameter)
{
CEdisComClientDlg* pClient = (CEdisComClientDlg*)lpParameter;
SOCKET sClient = pClient->GetClientSock();
FD_SET writefd;
FD_SET readfd;

while (pClient->isConning()) //连接正常
{
FD_ZERO(&writefd);
FD_ZERO(&readfd);
FD_SET(pClient->GetClientSock(), &readfd); //添加到可读
FD_SET(pClient->GetClientSock(), &writefd); //添加到可写

int reVal;
reVal = select(0, &readfd, &writefd, NULL, NULL); //等待满足的套接字
if (reVal == SOCKET_ERROR)
{
pClient->MessageBox(_T("select错误"));
return 0;
}
else if (reVal > 0)
{
if (FD_ISSET(pClient->GetClientSock(), &writefd)) //满足可写的套接字
{
//已处理
}
else if (FD_ISSET(pClient->GetClientSock(), &readfd)) //满足可读的套接字
{
pClient->ReadSrvData(pClient->GetClientSock());
}
}
}
return 0;
}
在服务器端,首先服务器侦听,当有客户端请求连接时,就新建一个sClient,用来accept客户端。然后我直接用这个sClient发送命令包给客户端,发送是可以成功的。但是我的理解是此时客户端应该有一个可读的套接字,即
else if (FD_ISSET(pClient->GetClientSock(), &readfd)) //满足可读的套接字
{
pClient->ReadSrvData(pClient->GetClientSock());
}
应该执行。但是当我启动服务器,调试客户端时,为什么没有被执行呢?
应当怎么样使用select模型
...全文
74 点赞 收藏 9
写回复
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
cftxlin 2009-09-18
我再补充一点,其实这就像打电话一样,你想跟某人打电话,你拨了电话号码后,对方听到了,拿起来了电话,并且“Hello”了一声后,此时你与你要找的人的说话的通道已经打开了。
回复
cftxlin 2009-09-18
觉得你的客户端的逻辑有点问题。

连接是客户端主动发起的,服务器端是被动的,这样服务器Select模式下才会检测到可读的套接字。
客户端连接服务器成功后,其实就可以直接进行收发数据的操作了,没有必要再用:
“reVal = select(0, &readfd, &writefd, NULL, NULL); //等待满足的套接字 ”
进行检测是否有可读的套接字,理应是检测不到的。
你的理解可能存在着一点偏差。

回复
tan625747 2009-09-17
,即
else if (FD_ISSET(pClient->GetClientSock(), &readfd)) //满足可读的套接字
{
pClient->ReadSrvData(pClient->GetClientSock());
}
应该执行。但是当我启动服务器,调试客户端时,为什么没有被执行呢?

///////////////////////////////////////////////////////////////////


要想被执行,在另一端必需有发送数据过来
回复
xylicon 2009-09-08
pServe->EstiClientState(addrClient);
pServe->AllotWork(sClient, addrClient);
我不知道你这2个函数里面是怎样实现的。

但要想select的可读工作,需要用你accept到的那个socket,即sClient。然后用send来发送。这样才能满足响应客户端select的可读工作
回复
dirdirdir3 2009-09-08
FD_SET等是linux下面的函数..................
回复
gxx2019 2009-09-08
我accept后,用这个accept向客户端发送数据了,即
//处理
pServe->EstiClientState(addrClient);
pServe->AllotWork(sClient, addrClient);
所以客户端应该是可读的
回复
whg01 2009-09-08
up
回复
xylicon 2009-09-08
当服务器accept客户端 之后,客户端应该是可写操作。
回复
jyh_baoding 2009-09-08
仔细的调试一下,注意函数返回失败时的错误码
回复
发动态
发帖子
网络编程
创建于2007-09-28

1.8w+

社区成员

VC/MFC 网络编程
申请成为版主
社区公告
暂无公告