登陆程序,为何在recv这里卡住了?

SweetLoverFT 2014-05-14 10:55:02
本人毕业设计做一个餐厅点菜系统,其基本思路是,客户端和服务器成功建立连接后,双向通信。
假定现在服务器端设置了用户账号密码为:“a”“123”,客户端先发送“Login:”命令,且已经被服务器端接收到了。
此时,客户端分2次分别发送用户填写的登陆账号和密码“a”“123”,服务企业能正常接收,判断后服务器反馈“LoginOK”,此时问题就出现了:客户端的recv执行之后一直卡死,无法执行下面的语句,在此想请教诸位兄台,下面是我的客户端服务器端代码。

客户端代码,MFC/C++
void CClientDlg::OnBnClickedBtnLogin()
{
// TODO: 在此添加控件通知处理程序代码
char cmd[MAX_BUF_SIZE];
if (!m_bConnectOK)
{
MessageBox(_T("请检查网络连接!"), _T("登陆"), MB_OK | MB_ICONERROR);
return;
}
m_bCanRecv = false;
UpdateData();
/*发送命令,已验证服务器可以收到*/
send(m_sockServer, "Login:", CMD_LENGTH + 1, 0);
memset(cmd, '\0', MAX_BUF_SIZE);
WideCharToMultiByte(CP_ACP, NULL, m_strUser.GetString(), m_strUser.GetLength(),
cmd, MAX_BUF_SIZE, NULL, NULL);
/*发送账号,已验证成功*/
send(m_sockServer, cmd, strlen(cmd) + 1, 0);
memset(cmd, '\0', MAX_BUF_SIZE);
WideCharToMultiByte(CP_ACP, NULL, m_strPassword.GetString(), m_strPassword.GetLength(),
cmd, MAX_BUF_SIZE, NULL, NULL);
/*发送密码,已验证成功*/
send(m_sockServer, cmd, strlen(cmd) + 1, 0);
/*下面这条语句执行完之后,MFC界面就一直卡住了,执行不了Sleep开始的语句*/
recv(m_sockServer, cmd, MAX_BUF_SIZE, 0);
Sleep(DELAY_TIME);
if (strcmp(cmd, "LoginOK") != 0)
MessageBox(_T("用户名密码不正确!"), _T("登录失败"), MB_OK | MB_ICONINFORMATION);
else
{
this->ShowWindow(SW_HIDE);
m_dlgOrder.DoModal();
this->ShowWindow(SW_SHOWNORMAL);
}
m_bCanRecv = true;
}

服务器端代码,MFC/C++
/*这个函数被调用的时候说明,"Login:"命令已经接收成功*/
LRESULT CServerDlg::OnLogin(WPARAM wParam, LPARAM lParam)
{
int i;
CString str;
char tmp[MAX_BUF_SIZE];
if (!m_bConnectOK)
{
MessageBox(_T("请检查网络连接!"), _T("登陆"), MB_OK | MB_ICONERROR);
m_bCanRecv = true;
return 0;
}
Sleep(DELAY_TIME);
/*接收用户名并验证,调试过成功*/
recv(m_SockClient, tmp, MAX_BUF_SIZE, 0);
str = tmp;
for (i = 0; i < QUEUE_LENGTH; i++)
if (customer[i].used && customer[i].user == str)
break;
Sleep(DELAY_TIME);
/*接受密码并验证,调试过成功*/
recv(m_SockClient, tmp, MAX_BUF_SIZE, 0);
str = tmp;
if (i < QUEUE_LENGTH && customer[i].password == str)
{
m_obj = i;
m_lstPlaceInf.SetItemText(0, 3, _T("上菜"));
/*发送验证结果,调试成功,发送没有问题,客户端接受有问题*/
send(m_SockClient, "LoginOK", strlen("LoginOK") + 1, 0);
}
else
send(m_SockClient, "LoginFailed", strlen("LoginFailed") + 1, 0);
m_bCanRecv = true;

return 0;
}
...全文
540 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
SweetLoverFT 2014-05-15
  • 打赏
  • 举报
回复
刚才代码贴的不好看,所以重新回复下 你说的很对,我没想到早上自己就发现这个问题了,用别的方法解决了,我要做的事是: 1.过段时间给分,作为对有人帮助我表示感谢; 2.自己阐释下,怎么解决的。

CClientDlg *pThis;
UINT CClientDlg::ThreadProc(LPVOID lpDump)
{
	int ret;
	CString str;
	char szBuf[MAX_BUF_SIZE];

	ASSERT(lpDump);
	pThis = (CClientDlg*)lpDump;
	while (!pThis->m_bExit)
	{
		if (pThis->m_bCanRecv)
		{
			memset(szBuf, '\0', MAX_BUF_SIZE);
			ret = recv(pThis->m_sockServer, szBuf, MAX_BUF_SIZE, 0);
			if (ret > 0)
			{
				str = szBuf;
				pThis->Analysis(str);
			}
			else
			{
				::MessageBox(NULL, _T("服务器掉线,请重新打开程序!"), _T("错误"), MB_OK | MB_ICONERROR);
				break;
			}
		}
	}

	return EXIT_SUCCESS;
}
虽然控制标记字 m_bCanRecv,起到了控制线程的作用,但是由于登陆是由点击按钮发送的,点击按钮发送的消息,被分析命令并处理拦截解决,并在处理前设置控制标记字不允许接收。此时就是服务器处理函数内部与客户端进行双向通讯了,由于 recv 是阻塞的,在设置控制标记字之前实际上是在等待要接受的信息,因此设置之后,还是要接受一条命令,才能做出响应。而此时,问题就在此,原本要指定发送给客户端登陆结果的"LoginOK""LoginFailed",被客户端的命令分析线程吞噬,所以导致客户端内部处理函数的recv一直处于等待接收登陆结果的状态,因此卡死。 不知道楼主可否回复一下如何编写一个“一对多”的服务器/客户端测试样例程序分享给我呢?可以发送到我的邮箱:SweetLoverFT@qq.com,那样的话我会再加分还给你。
SweetLoverFT 2014-05-15
  • 打赏
  • 举报
回复
你说的很对,我没想到早上自己就发现这个问题了,用别的方法解决了,我要做的事是: 1.过段时间给分,作为对有人帮助我表示感谢; 2.自己阐释下,怎么解决的。 我的接收线程是: static DWORD CClientDlg::ThreadProc(LPVOID lpDump) { int ret; CString str; char szBuf[MAX_BUF_SIZE]; ASSERT(lpDump); pThis = (CClientDlg*)lpDump; while (!pThis->m_bExit) { if (pThis->m_bCanRecv) { memset(szBuf, '\0', MAX_BUF_SIZE); ret = recv(pThis->m_sockServer, szBuf, MAX_BUF_SIZE, 0); if (ret > 0) { str = szBuf; pThis->Analysis(str); } else { ::MessageBox(NULL, _T("服务器掉线,请重新打开程序!"), _T("错误"), MB_OK | MB_ICONERROR); break; } } } return EXIT_SUCCESS; } 虽然控制标记字 m_bCanRecv,起到了控制线程的作用,但是由于登陆是由点击按钮发送的,点击按钮发送的消息,被分析命令并处理拦截解决,并在处理前设置控制标记字不允许接收。此时就是服务器处理函数内部与客户端进行双向通讯了,由于 recv 是阻塞的,在设置控制标记字之前实际上是在等待要接受的信息,因此设置之后,还是要接受一条命令,才能做出响应。而此时,问题就在此,原本要指定发送给客户端登陆结果的"LoginOK""LoginFailed",被客户端的命令分析线程吞噬,所以导致客户端内部处理函数的recv一直处于等待接收登陆结果的状态,因此卡死。 不知道楼主可否回复一下如何编写一个“一对多”的服务器/客户端测试样例程序分享给我呢?可以发送到我的邮箱:SweetLoverFT@qq.com,那样的话我会再加分还给你。
Eleven 2014-05-15
  • 打赏
  • 举报
回复
在你服务器端send以后Sleep一下,在看看客户端能收到东西吗?不是你服务器端send以后做了什么?

18,356

社区成员

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

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