请问:如何对Socket循环发送进行控制

时间:2022-12-15 16:47:04
MFC工程:
1. 一个编辑框,一个复选按钮,两个普通按钮(一个用于开始,一个用于结束)。

2. 创建SOCKET, 初始化等等。非阻塞套接字。TCP/UDP

功能说明:

1. 复选按钮工作:

   (1)当选中时,立即循环的发送编辑框中的内容。
       
   这里的循环发送是指把编辑框的内容全部读出,然后发送。发送完成后,再次读取同样的内容,然后再次发送同样的内容。
    
   如此反复。
   
   (2)在循环发送的过程中,如果取消选中即停止发送。注意:*在发送过程中停止。我自己实现的时候发现不能停止。不知道什么原因。

2. 按钮工作:
     
   一个用于开始发送。
   一个用于停止发送。注意:*在发送过程中停止。

以上的两个功能不知道如何实现。

8 个解决方案

#1


1.楼主 MFC 基本的界面编程有没有做过,就是说这些界面元素如何添加,如何绑定处理函数?
2.socket编程基本api如何使用,最简单的过程是怎么样的是否知道

如果上面说的不清楚的话,建议先去学下基础知识.
关于MFC看 <深入浅出mfc>
关于socket看<windows网络编程>吧

都是基础书籍,帮助你了解

#2


下点视频来看吧,这些方面的视频都有

#3


jwybobo2007你好,
你说的那1、2问题都看过,也可以实现单次的通信。

代码很多,不然贴上了。

大概说下我的实现过程:
1. 定义了一个InitSock()函数。实现了初始化工作。

其中用WSAASyncSelect注册了FD_READ|FD_CLOSE事件。

2. 对某个按钮实现了发送工作。
   实现的过程是调用了一次OnSend函数。

3. OnSend函数的功能是:
  提取编辑框中内容,并在
    --TCP,发送到SOCKET上。
    --UDP, 发送到目标IP和端口。

4. 我对复选按钮进行了响应,想在里边do...while来调用OnSend函数,但是发现出不来了(单步调试发现)。
   也就是说,我不能在再点击复选按钮让此循环结束。

郁闷中。

现在有想用定时器来实现,也就是:
步骤:
1.在响应复选按钮中定义一个定时器
2.在定时器中调用OnSend函数。
3.在复选按钮未选中时,KillTimer


不知明白我的问题在哪吗。

谢谢,by the way.

#4


如果do...while为死循环,别的得不到调度当然不能修改了,可以采用线程的方式就可以了。

#5


引用 3 楼 joromeh 的回复:
jwybobo2007你好,
你说的那1、2问题都看过,也可以实现单次的通信。

代码很多,不然贴上了。

大概说下我的实现过程:
1. 定义了一个InitSock()函数。实现了初始化工作。

其中用WSAASyncSelect注册了FD_READ|FD_CLOSE事件。

2. 对某个按钮实现了发送工作。
  实现的过程是调用了一次OnSend函数。

3. OnSe……

你用定时器或者加开线程可以解决,就思路的话,去做就是了,应该可以解决

#6


你用do while想退出的话,就得设定一个退出条件啊。。。而这个条件,就让退出按钮执行时使成立.

#7


这个条件可以设为静态BOOL值成员变量,或者全局变量。

#8


我之前用的两种方法:
实现1:
============================
复选按钮的响应:
void CEx01aView::OnCheckAutoSend() 
{
GetDlgItem(IDC_BTN_STOP)->EnableWindow(TRUE);

UpdateData(TRUE);

if (m_bIsAutoSend)
{
OnSend();
}

}

OnSend函数:
BOOL CEx01aView::OnSend()
{
UpdateData(TRUE);

CString strSend;
DWORD dwSend;
int len;
GetDlgItemText(IDC_EDIT_SEND,strSend);
len=strSend.GetLength();
if (strSend == "")
{
MessageBox("请输入发送的数据!");
return FALSE;
}

m_wsaSendBuf.buf=strSend.GetBuffer(len);
m_wsaSendBuf.len=len;

do
{
if (!m_bIsTcp)
{
if(SOCKET_ERROR==WSASendTo(m_socket,&m_wsaSendBuf,1,&dwSend,0,
(SOCKADDR*)&m_addrTo,sizeof(SOCKADDR),NULL,NULL))
{
MessageBox("UDP发送数据失败!");
return FALSE;
}

m_dwSCount += dwSend; // m_dwSCount 为静态变量,统计发送字节
}
else
{
if(SOCKET_ERROR==WSASend(m_socket,&m_wsaSendBuf,1,&dwSend,0,
NULL,NULL))
{
MessageBox("TCP发送数据失败!");
return FALSE;
}

m_dwSCount += dwSend;
}

m_dwSendCount = m_dwSCount;
UpdateData(FALSE);
//SetDlgItemText(IDC_EDIT_SEND,"");

                // 想在此判断复选为未选中时,结束,不过,行不通。
                // 循环死了
UpdateData(TRUE);
if (!m_bIsAutoSend)
break;

}while(m_bIsAutoSend);

return TRUE;
}

实现2:
==========================================
void CEx01aView::OnCheckAutoSend() 
{
GetDlgItem(IDC_BTN_STOP)->EnableWindow(TRUE);

UpdateData(TRUE);

while (m_bIsAutoSend) 
{
OnSend(); // 去掉了函数中的循环,而在这里实现

// 想在此判断复选为未选中时结束,不过,行不通。
UpdateData(TRUE);
if (!m_bIsAutoSend)
break;
}

}

BOOL CEx01aView::OnSend()
{
UpdateData(TRUE);

CString strSend;
DWORD dwSend;
int len;
GetDlgItemText(IDC_EDIT_SEND,strSend);
len=strSend.GetLength();
if (strSend == "")
{
MessageBox("请输入发送的数据!");
return FALSE;
}

m_wsaSendBuf.buf=strSend.GetBuffer(len);
m_wsaSendBuf.len=len;


if (!m_bIsTcp)
{
if(SOCKET_ERROR==WSASendTo(m_socket,&m_wsaSendBuf,1,&dwSend,0,
(SOCKADDR*)&m_addrTo,sizeof(SOCKADDR),NULL,NULL))
{
MessageBox("UDP发送数据失败!");
return FALSE;
}

m_dwSCount += dwSend;
}
else
{
if(SOCKET_ERROR==WSASend(m_socket,&m_wsaSendBuf,1,&dwSend,0,
NULL,NULL))
{
MessageBox("TCP发送数据失败!");
return FALSE;
}

m_dwSCount += dwSend;
}

m_dwSendCount = m_dwSCount;
UpdateData(FALSE);
//SetDlgItemText(IDC_EDIT_SEND,"");

return TRUE;
}


最后用定时来实现可以了:
实现3:
=====================================
void CEx01aView::OnCheckAutoSend() 
{
GetDlgItem(IDC_BTN_STOP)->EnableWindow(TRUE);

UpdateData(TRUE);

if (m_bIsAutoSend)
SetTimer(2, 1000, NULL);
else
KillTimer(2);
}

void CEx01aView::OnTimer(UINT nIDEvent) 
{
// TODO: Add your message handler code here and/or call default
switch(nIDEvent)
{
case 1:
//此处省略。。。
break;
case 2:
OnSend();
break;
}

CFormView::OnTimer(nIDEvent);
}

最后,终于可以实现了,当选中复选按钮时发送,未选中时停止发送的功能。

谢谢各位大大。
。。。。

#1


1.楼主 MFC 基本的界面编程有没有做过,就是说这些界面元素如何添加,如何绑定处理函数?
2.socket编程基本api如何使用,最简单的过程是怎么样的是否知道

如果上面说的不清楚的话,建议先去学下基础知识.
关于MFC看 <深入浅出mfc>
关于socket看<windows网络编程>吧

都是基础书籍,帮助你了解

#2


下点视频来看吧,这些方面的视频都有

#3


jwybobo2007你好,
你说的那1、2问题都看过,也可以实现单次的通信。

代码很多,不然贴上了。

大概说下我的实现过程:
1. 定义了一个InitSock()函数。实现了初始化工作。

其中用WSAASyncSelect注册了FD_READ|FD_CLOSE事件。

2. 对某个按钮实现了发送工作。
   实现的过程是调用了一次OnSend函数。

3. OnSend函数的功能是:
  提取编辑框中内容,并在
    --TCP,发送到SOCKET上。
    --UDP, 发送到目标IP和端口。

4. 我对复选按钮进行了响应,想在里边do...while来调用OnSend函数,但是发现出不来了(单步调试发现)。
   也就是说,我不能在再点击复选按钮让此循环结束。

郁闷中。

现在有想用定时器来实现,也就是:
步骤:
1.在响应复选按钮中定义一个定时器
2.在定时器中调用OnSend函数。
3.在复选按钮未选中时,KillTimer


不知明白我的问题在哪吗。

谢谢,by the way.

#4


如果do...while为死循环,别的得不到调度当然不能修改了,可以采用线程的方式就可以了。

#5


引用 3 楼 joromeh 的回复:
jwybobo2007你好,
你说的那1、2问题都看过,也可以实现单次的通信。

代码很多,不然贴上了。

大概说下我的实现过程:
1. 定义了一个InitSock()函数。实现了初始化工作。

其中用WSAASyncSelect注册了FD_READ|FD_CLOSE事件。

2. 对某个按钮实现了发送工作。
  实现的过程是调用了一次OnSend函数。

3. OnSe……

你用定时器或者加开线程可以解决,就思路的话,去做就是了,应该可以解决

#6


你用do while想退出的话,就得设定一个退出条件啊。。。而这个条件,就让退出按钮执行时使成立.

#7


这个条件可以设为静态BOOL值成员变量,或者全局变量。

#8


我之前用的两种方法:
实现1:
============================
复选按钮的响应:
void CEx01aView::OnCheckAutoSend() 
{
GetDlgItem(IDC_BTN_STOP)->EnableWindow(TRUE);

UpdateData(TRUE);

if (m_bIsAutoSend)
{
OnSend();
}

}

OnSend函数:
BOOL CEx01aView::OnSend()
{
UpdateData(TRUE);

CString strSend;
DWORD dwSend;
int len;
GetDlgItemText(IDC_EDIT_SEND,strSend);
len=strSend.GetLength();
if (strSend == "")
{
MessageBox("请输入发送的数据!");
return FALSE;
}

m_wsaSendBuf.buf=strSend.GetBuffer(len);
m_wsaSendBuf.len=len;

do
{
if (!m_bIsTcp)
{
if(SOCKET_ERROR==WSASendTo(m_socket,&m_wsaSendBuf,1,&dwSend,0,
(SOCKADDR*)&m_addrTo,sizeof(SOCKADDR),NULL,NULL))
{
MessageBox("UDP发送数据失败!");
return FALSE;
}

m_dwSCount += dwSend; // m_dwSCount 为静态变量,统计发送字节
}
else
{
if(SOCKET_ERROR==WSASend(m_socket,&m_wsaSendBuf,1,&dwSend,0,
NULL,NULL))
{
MessageBox("TCP发送数据失败!");
return FALSE;
}

m_dwSCount += dwSend;
}

m_dwSendCount = m_dwSCount;
UpdateData(FALSE);
//SetDlgItemText(IDC_EDIT_SEND,"");

                // 想在此判断复选为未选中时,结束,不过,行不通。
                // 循环死了
UpdateData(TRUE);
if (!m_bIsAutoSend)
break;

}while(m_bIsAutoSend);

return TRUE;
}

实现2:
==========================================
void CEx01aView::OnCheckAutoSend() 
{
GetDlgItem(IDC_BTN_STOP)->EnableWindow(TRUE);

UpdateData(TRUE);

while (m_bIsAutoSend) 
{
OnSend(); // 去掉了函数中的循环,而在这里实现

// 想在此判断复选为未选中时结束,不过,行不通。
UpdateData(TRUE);
if (!m_bIsAutoSend)
break;
}

}

BOOL CEx01aView::OnSend()
{
UpdateData(TRUE);

CString strSend;
DWORD dwSend;
int len;
GetDlgItemText(IDC_EDIT_SEND,strSend);
len=strSend.GetLength();
if (strSend == "")
{
MessageBox("请输入发送的数据!");
return FALSE;
}

m_wsaSendBuf.buf=strSend.GetBuffer(len);
m_wsaSendBuf.len=len;


if (!m_bIsTcp)
{
if(SOCKET_ERROR==WSASendTo(m_socket,&m_wsaSendBuf,1,&dwSend,0,
(SOCKADDR*)&m_addrTo,sizeof(SOCKADDR),NULL,NULL))
{
MessageBox("UDP发送数据失败!");
return FALSE;
}

m_dwSCount += dwSend;
}
else
{
if(SOCKET_ERROR==WSASend(m_socket,&m_wsaSendBuf,1,&dwSend,0,
NULL,NULL))
{
MessageBox("TCP发送数据失败!");
return FALSE;
}

m_dwSCount += dwSend;
}

m_dwSendCount = m_dwSCount;
UpdateData(FALSE);
//SetDlgItemText(IDC_EDIT_SEND,"");

return TRUE;
}


最后用定时来实现可以了:
实现3:
=====================================
void CEx01aView::OnCheckAutoSend() 
{
GetDlgItem(IDC_BTN_STOP)->EnableWindow(TRUE);

UpdateData(TRUE);

if (m_bIsAutoSend)
SetTimer(2, 1000, NULL);
else
KillTimer(2);
}

void CEx01aView::OnTimer(UINT nIDEvent) 
{
// TODO: Add your message handler code here and/or call default
switch(nIDEvent)
{
case 1:
//此处省略。。。
break;
case 2:
OnSend();
break;
}

CFormView::OnTimer(nIDEvent);
}

最后,终于可以实现了,当选中复选按钮时发送,未选中时停止发送的功能。

谢谢各位大大。
。。。。