tcp + 阻塞 + 多線程 => 如何停止Recv()

http://topic.csdn.net/t/20051117/01/4398756.html

TCP的阻塞模式,服務器程序

主線程 => 界面
線程2 => Accept()
線程3 => Recv()

線程2在Accept了一個Client的連接後返回一個TCP Socket,我把它放到線程3來接收資料。

問題是在Recv()在沒有資料到來的時候會一直等待,我想在收到界面命令的時候令到它停止等待。

請各位給個正確的思路!
=========================

设置socket超时间隔,比如100毫秒,主线程退出时用变量标志通知socket线程,socket线程超时查询主线程是否在退出,退出则自己也退出.
=========================
关闭其socket时,recv()自动退出。
=========================
异步模型就可以了阿

mfc 的话可以换一个socket类

其他的话可以用select ,

windows overlapper I/O
IO CP

都可以阿
========================
要设置为非阻塞模式,使用select等i/o模型进行管理,可以方便的退出
=======================
wwwllg(wwwllg)
〞Select〞 -〉 是不是在其他的位置調用Select就可以令到Recv()返回了?能解釋一下嗎?

alen_ghl(东方求*)
"第三个线程再设置一下线程退出的条件" -〉 這個跟線程的關係不大。

lianglp()
〞关闭其socket时,recv()自动退出。〞 -〉 當然這是一個辦法,但卻是最不理想的辦法。

somexing(张星星)
〞异步模型就可以了阿〞 -〉 我也知道,但是我要的是阻塞模式

softrain(敢笑杨过不痴情)
〞设置socket超时间隔,比如100毫秒,主线程退出时用变量标志通知socket线程,socket线程超时查询主线程是否在退出,退出则自己也退 出.〞-〉 我也是想這樣子用,但在這個時間方面較難決定,而且萬一接收的數據大的時候,不知道這個Timeout的時間會不會影響到它。
========================================

11 楼THINK511() 回复于 2005-11-17 16:14:53 得分 0

你的线程3中一定是使用的
while(1)
{
...
recv();
...
}
的结构的,你只要在线程2中收到一个连接就向主线程发消息告知连接的SOCKET(就叫sock吧),当主线程要停止等待时只要 closesocket(sock)就可以关闭这个SOCKET,那么上面的while循环也会退出,这样线程3也就关闭了。也就不需要等待了。阻塞式的 recv只有使用这种方法,否则你就只有使用非阻塞方式了。
=========================================

12 楼abrams2004(tomcat) 回复于 2005-11-17 18:32:28 得分 0

设置socket设置SO_RCVTIMEO参数好了,在一定时间内没有数据,就退出循环
========================================

13 楼niu_a(阿牛) 回复于 2005-11-17 19:12:43 得分 0

可能shutdown应该比closesocket温柔一点Top

14 楼sevencat(七猫) 回复于 2005-11-17 20:26:17 得分 0

1、可以用CSocket修改版
2、lianglp()
〞关闭其socket时,recv()自动退出。〞 -〉 當然這是一個辦法,但卻是最不理想的辦法。
我觉得这是比较理想的办法。
======================================

16 楼somexing(somexing) 回复于 2005-11-18 13:17:55 得分 0

TerminateThread()
杀掉那个线程不行?
======================================

22 楼icegirl914(冰儿) 回复于 2005-11-22 10:41:22 得分 0

LZ的问题跟我现在做的有点象,我的接收线程平时是挂起的,只有在AccpeT收到接收请求是才会启动接收处理,接收处理完后就又挂起了。
======================================

27 楼DoItFreely(Freely) 回复于 2005-11-22 17:48:57 得分 0

使用事件就行了
WSAEventSelect();
然后WaitForSingleObject()
要退出的话只要在外面SetEvent()一把
======================================




http://topic.csdn.net/t/20030522/01/1816659.html

楼主jerry_mouse() 2003-05-22 01:27:59 在 VC/MFC / 进程/线程/DLL 提问

有一个监听Socket连接的线程,代码为:
{
while(!pThread->m_bExit)
{
if(listen(m_hSocket, SOMAXCONN) == SOCKET_ERROR)
{
continue;
}

SOCKADDR addr;
int addrlen = sizeof(SOCKADDR);

SOCKET hSocket = accept(m_hSocket, &addr, &addrlen);
if(hSocket == INVALID_SOCKET)
{
continue;
}
m_lSocket.AddTail(hSocket);

Sleep(100);
}
}

这个线程运行是会在listen处阻塞,所以在进程退出时把bExit置为true线程也不会退出,我现在采用的方法是先用closesocket(m_hSocket)关闭Socket,这样listen就会立刻返回,但不知道这样会不会有问题。
另外,好象对这种线程有一种使用信号(Event)来控制的方法,听说是最安全的,那位大侠有这方面的经验,给小弟讲讲吧,最好有个例子,谢谢大家:)
===============================
你的做法是正确的,在server端先关闭listen socket使之不再接受新的连接请求,然后退出服务.

listen()是阻塞型,无论是你是现在这种方法,还是采用event都没有办法使之从阻塞状态退出,你只能用closesocket()的方法强行使之退出.使用event之所以"安全",是因为相对于你的
pThread->m_bExit来说event不是出现同步问题,而你的pThread->m_bExit是个共享变量,某种程度上还是有同步问题的.

至于能否使listen()象send(),recv()从阻塞变成非阻塞型,我一点头绪都没有.
===============================

2 楼tserpent(Tang) 回复于 2003-05-22 08:28:02 得分 10

listen()怎么会是阻塞的呢?accept()才是阻塞的。你的做法有问题,不应该把listen()放在while循环中,
if(listen(m_hSocket, SOMAXCONN) == SOCKET_ERROR)
{
return error;
}

while(!pThread->m_bExit)
{
SOCKADDR addr;
int addrlen = sizeof(SOCKADDR);

SOCKET hSocket = accept(m_hSocket, &addr, &addrlen);
if(hSocket == INVALID_SOCKET)
{
continue;
}
m_lSocket.AddTail(hSocket);

Sleep(100);
}

如果推出的,那只有破坏其阻塞条件了。
Top

3 楼jerry_mouse() 回复于 2003-05-23 00:00:46 得分 0

to:Zark(金陵五月)
可否举个例子,还有“使用event之所以"安全",是因为相对于你的pThread->m_bExit来说event不是出现同步问题”,为什么使用event不会出现同步问题,event我没有实际使用过,可否消息讲讲,谢谢。Top

4 楼Zark(金陵五月) 回复于 2003-05-23 05:25:14 得分 0

event本质上说就是一个变量,但它是在kernel级加锁的,所以不会出现两个以上线程同时读写的情况.而是你的变量则是有可能(当然由于你的那个m_bExit的读写是十分简单的,实际上也不会出现同步错误,但在理论上却是存在同步错误的可能的)
Top

5 楼muddogxp(土狗) 回复于 2003-05-23 08:41:04 得分 10

re:tser
listen不为阻塞,应该把accept发在循环里和listen分开。
至于event,这个是内核对象,存在就是为了解决线程同步的某些问题的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值