在运行控制台程序的时候,按下Ctrl+C程序就会马上终止吗?

ww884203 2012-05-09 02:25:57
今天在学习网络的时候发现一个小问题,问题是这样的:
我在控制台下面写了一个UDPServer和一个UDPClient,其中UDPServer只负责recv数据并显示到控制台上,而UDPClient则接受用户的输入并发送到UDPServer。我的问题是,比如我在UDPClient中输入指定条数的数据让程序正常退出,那么程序没有任何问题,但是如果我输入了一条数据以后,按下Ctrl+C强制退出UDPClient,那么之前留在缓冲区里面的数据会被再次发送一遍。
比如说,我在UDPClient里面输入 nihaoma? , UDPServer正确的接受了这条语句并且将它显示出来,这时候我用Ctrl+C退出UDPClient,UDPServer又一次收到了一条 nihaoma? ,请问这是怎么回事?按下Ctrl+C后,它后面的代码也会执行吗?如果执行的话,在怎么样的条件下会执行,怎么样又不执行呢?
附UDPClient在发送那一部分的代码:

for(i = 0 ; i != dwCount ; ++i)
{
gets(sendbuf); //按下Ctrl+C的时候,程序应该是阻塞在这一条语句的
ret = sendto(s,sendbuf,dwLength,0,(sockaddr *)&recipent,sizeof(recipent));
printf("sendto message[%d]\n",++times); //但是这里的语句也被执行了
if(ret == SOCKET_ERROR)
{
printf("sendto() failed with error %d\n",WSAGetLastError());
break;
}
else if(ret == 0)
{
break;
}
}
...全文
898 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
ww884203 2012-05-09
  • 打赏
  • 举报
回复
单步调试的时候感觉按下Ctrl+C仅仅是跳过了gets这一行语句啊,在正常运行的时候Ctrl+C会让程序退出,而在断点调试运行的时候,仅仅只是gets没有被执行,执行结束后还能返回到循环继续运行啊。。。
ww884203 2012-05-09
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]

你这个问题确实没有碰到过, 不过正常情况下程序不应该用 Ctrl+C去结束, 你应该 判断输入的字符串是不是quit是则推出

在 gets(sendbuf); 这行代码后面添加

if (strcmp(sendbuf, "QUIT"))==0)
{
exit(1);
}
[/Quote]
我以前一直是这么干的。。。不过自己测试一下的话就干脆用Ctrl+C退出得了,结果就遇到这个问题。
我待会儿去单步调试一下看看结果怎么样
赵4老师 2012-05-09
  • 打赏
  • 举报
回复
以上代码节选自:
console屏幕处理例子程序。终端窗口屏幕处理相关API使用例子。来自MSVC20\SAMPLES\win32\console\
http://download.csdn.net/detail/zhao4zhong1/3461309
赵4老师 2012-05-09
  • 打赏
  • 举报
回复
/*********************************************************************
* FUNCTION: demoSetCtrlHandler(HANDLE hConOut) *
* *
* PURPOSE: demonstrate SetConsoleCtrlHandler by setting a ctrl+break *
* and ctrl+c handler. When the user hits either one of *
* these keys, a message is printed to the console *
* indicating the event. *
* *
* INPUT: the output handle to write to *
*********************************************************************/

void demoSetCtrlHandler(HANDLE hConOut)
{
BOOL bSuccess;

setConTitle(__FILE__);
hConsole = hConOut; /* set global console output handle for handler */
myPuts(hConOut, "Let's install a ctrl+c and ctrl+break handler for this\n"
"process. Hit ctrl+c and ctrl+break a few times to test\n"
"the handler. Hit enter to return...");
/* set handler for this process */
bSuccess = SetConsoleCtrlHandler(handler_routine, TRUE);
PERR(bSuccess, "SetConsoleCtrlHandler");
/* wait for user to hit enter */
while (myGetchar() != 0xd)
;
/* now let's generate some control events */
myPuts(hConOut, "Now we'll use GenerateConsoleCtrlEvent to generate a\n"
"ctrl+c and a ctrl+break event...\n");
bSuccess = GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
PERR(bSuccess, "GenerateConsoleCtrlEvent");
bSuccess = GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, 0);
PERR(bSuccess, "GenerateConsoleCtrlEvent");
Sleep(1000); /* give ctrl handle time to output messages */
myPuts(hConOut, "\nNow choose 'Close' then 'Cancel' from the system\n"
"menu of this console and note that we receive a\n"
"CTRL_CLOSE_EVENT...\n");
myPuts(hConOut, "\nHit enter to continue...");
myGetchar();
/* remove our handler from the list of handlers */
bSuccess = SetConsoleCtrlHandler(handler_routine, FALSE);
PERR(bSuccess, "SetConsoleCtrlHandler");
return;
}
赵4老师 2012-05-09
  • 打赏
  • 举报
回复
signal Constants
#include <signal.h>

Remarks

The sig argument must be one of the manifest constants listed below (defined in SIGNAL.H).

SIGABRT

Abnormal termination. The default action terminates the calling program with exit code 3.

SIGFPE

Floating-point error, such as overflow, division by zero, or invalid operation. The default action terminates the calling program.

SIGILL

Illegal instruction. The default action terminates the calling program.

SIGINT

CTRL+C interrupt. The default action issues INT 23H.

SIGSEGV

Illegal storage access. The default action terminates the calling program.

SIGTERM

Termination request sent to the program. The default action terminates the calling program.

See Also signal, raise
liuwons 2012-05-09
  • 打赏
  • 举报
回复
断电单步调试
ww884203 2012-05-09
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 的回复:]

写了半天我看到是WINDOWS,瞬间什么也不说了,下边是注意到是WINDOWS以前写的。

这个问题我也不懂,我只能猜测一下,可能是信号投递到该线程之后中断了read调用与实际退出动作之间有时间差。

1,gets函数不应该使用,如果你了解一下fgets你自己就怕用gets了,使用fgets取代是第一步。
2,应该判断fgets返回值,如果返回的是NULL,你也要sendto(NULL……
[/Quote]
好的,谢谢。。。不过我只是刚刚接触网络这一块,写一个非常简单的UDP程序测试一下而已。。。所以不规范的地方很多,请多多包涵。。。
现在也开始研究LINUX了,我还很菜,到时候有问题就上论坛来问,请多指教,呵呵
W170532934 2012-05-09
  • 打赏
  • 举报
回复
下断点,仔细查看!
langeldep 2012-05-09
  • 打赏
  • 举报
回复
刚才给你测试了一把, 确实如你所说, ctrl+C后, 往下执行了。
langeldep 2012-05-09
  • 打赏
  • 举报
回复
你这个问题确实没有碰到过, 不过正常情况下程序不应该用 Ctrl+C去结束, 你应该 判断输入的字符串是不是quit是则推出

在 gets(sendbuf); 这行代码后面添加

if (strcmp(sendbuf, "QUIT"))==0)
{
exit(1);
}
qq120848369 2012-05-09
  • 打赏
  • 举报
回复
写了半天我看到是WINDOWS,瞬间什么也不说了,下边是注意到是WINDOWS以前写的。

这个问题我也不懂,我只能猜测一下,可能是信号投递到该线程之后中断了read调用与实际退出动作之间有时间差。

1,gets函数不应该使用,如果你了解一下fgets你自己就怕用gets了,使用fgets取代是第一步。
2,应该判断fgets返回值,如果返回的是NULL,你也要sendto(NULL)吗?
3, Ctrl+C就是向进程kill一个SIGINT信号,我测试过fgets里的read会忽略EINTR继续read,对我没有什么帮助。
4,我见过的服务端,全部都是通过全局变量static volatile sig_atomic_t should_exit配合信号处理函数来检测用户kill信号的,程序需要定时轮询以便检测。
5,最终建议你使用select检测0,设置0非阻塞,并且使用read读取键盘数据,自行根据\n拆行,Ctrl+C信号应当注册信号处理函数,select超时定时检测退出变量是否设置。

赵4老师 2012-05-09
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 的回复:]
引用 10 楼 的回复:

特在此重现莫名其妙隐身的6楼

赵老师能不能说一下程序调试的技巧,谢谢!我用的是VS2010
[/Quote]
比如通读MSDN2008中的“使用 Visual Studio 进行调试”
ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.chs/dv_vsdebug/html/590f152d-31e2-4e13-b808-a1b13e421483.htm
ww884203 2012-05-09
  • 打赏
  • 举报
回复
比如说在LINUX系统下使用signal(SIGINT , sig_int)函数到话,当按下Ctrl+C,程序收到SIGINT信号到时候,sig_int函数就会被执行,我想请问这两者之间是不是有关系呢?
hnzmdzcm 2012-05-09
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 的回复:]

特在此重现莫名其妙隐身的6楼
[/Quote]
赵老师能不能说一下程序调试的技巧,谢谢!我用的是VS2010
赵4老师 2012-05-09
  • 打赏
  • 举报
回复
特在此重现莫名其妙隐身的6楼
/*********************************************************************
* FUNCTION: demoSetCtrlHandler(HANDLE hConOut) *
* *
* PURPOSE: demonstrate SetConsoleCtrlHandler by setting a ctrl+break *
* and ctrl+c handler. When the user hits either one of *
* these keys, a message is printed to the console *
* indicating the event. *
* *
* INPUT: the output handle to write to *
*********************************************************************/

void demoSetCtrlHandler(HANDLE hConOut)
{
BOOL bSuccess;

setConTitle(__FILE__);
hConsole = hConOut; /* set global console output handle for handler */
myPuts(hConOut, "Let's install a ctrl+c and ctrl+break handler for this\n"
"process. Hit ctrl+c and ctrl+break a few times to test\n"
"the handler. Hit enter to return...");
/* set handler for this process */
bSuccess = SetConsoleCtrlHandler(handler_routine, TRUE);
PERR(bSuccess, "SetConsoleCtrlHandler");
/* wait for user to hit enter */
while (myGetchar() != 0xd)
;
/* now let's generate some control events */
myPuts(hConOut, "Now we'll use GenerateConsoleCtrlEvent to generate a\n"
"ctrl+c and a ctrl+break event...\n");
bSuccess = GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
PERR(bSuccess, "GenerateConsoleCtrlEvent");
bSuccess = GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, 0);
PERR(bSuccess, "GenerateConsoleCtrlEvent");
Sleep(1000); /* give ctrl handle time to output messages */
myPuts(hConOut, "\nNow choose 'Close' then 'Cancel' from the system\n"
"menu of this console and note that we receive a\n"
"CTRL_CLOSE_EVENT...\n");
myPuts(hConOut, "\nHit enter to continue...");
myGetchar();
/* remove our handler from the list of handlers */
bSuccess = SetConsoleCtrlHandler(handler_routine, FALSE);
PERR(bSuccess, "SetConsoleCtrlHandler");
return;
}

64,682

社区成员

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

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