⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 subject_61593.htm

📁 vc
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<p>
序号:61593 发表者:badboy 发表日期:2003-11-20 15:23:47
<br>主题:关于CSOCKET多线程问题!
<br>内容:我在研究的这个程序是《VC网络高级编程》里的局域网聊天程序,是C/S结构的。可以有多个客户同时聊天。我在《VC网络高级编程》第76页看到一句话,“Csocket对象实际上是个一个两态对象,有时同步,有时异步。&nbsp;&nbsp; ……当CSocketFile与归档对象一起使用时,它具有更好的性能,并减少了“死锁”的危险。死锁意味着发送和接受套接字都在等待对方,或等待一个通用资源。当然如果CArchive对象与CSocketFile一起并以CFile对象的方式工作,这种情况还是可能发生。”<BR>&nbsp;&nbsp;&nbsp;&nbsp; “死锁”我就不说了,大家应该知道。但是在这个聊天程序里,我一点都没有看到关于多线程同步的东西,没有看到任何可以让线程同步的对象(比如互斥器,信号量)。既然我控制不了线程,我怎么去预防死锁?<BR>&nbsp;&nbsp; 原来我也以为要程序员自己来控制每个套接字的同步,比如,当前服务器正在接受一台客户机的数据时,恰好别的客户机也来了数据,你说,怎么办?套接字处于阻塞模式?<BR>&nbsp;&nbsp; 套接字可以处于阻塞模式或非阻塞模式?<BR>&nbsp;&nbsp;&nbsp;&nbsp;什么意思? 套接字简单说就代表一个通信端口,说他阻塞,是不是就是说,此时他正在忙着呢,没空搭理别的套接字的通信请求? 说他非阻塞,就是说,他现在正闲着呢! 是这个意思吗?<BR>&nbsp;&nbsp;书上说,“调用一个阻塞模式的函数都会产生相同的后果,——耗费或短或长的的时间等待操作的完成。”这句话又是什么意思?<BR>&nbsp;&nbsp; 谁有关于套接字阻塞模式、非阻塞模式与多线程关系的资料!<BR>&nbsp;&nbsp;&nbsp;&nbsp;
<br><a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p>
<hr size=1>
<blockquote><p>
回复者:BigJames 回复日期:2003-11-20 19:29:18
<br>内容:不要一下子问太多问题:)<BR>阻塞模式是说send, recv这样的调用会使所在的进程/线程处于挂起等待状态,除非收到数据,否则程序不会继续执行。
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
<hr size=1>
<blockquote><p>
回复者:badboy 回复日期:2003-11-21 12:08:45
<br>内容:凭感觉,就觉得你说的对!<BR><BR>&nbsp;&nbsp; 不过,请继续!
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
<hr size=1>
<blockquote><p>
回复者:BigJames 回复日期:2003-11-21 12:46:32
<br>内容:标准的SOCKET,不包含同步功能,需要程序自己控制<BR>在编程模式上,阻塞式的socket可以通过select达到一个进程/线程同时处理多个socket的目的。<BR>也可以用socket+thread的方式来做。
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
<hr size=1>
<blockquote><p>
回复者:badboy 回复日期:2003-11-21 13:54:39
<br>内容:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果书上跟你说的一样就好理解了! 书上偏偏说:“调用一个阻塞模式的函数都会产生相同的后果” 书上的这句话,似乎好象,也许,可能是说,函数也分为两种,一种是阻塞模式的函,一种是非阻塞模式的函数。&nbsp;&nbsp; 对吗?
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
<hr size=1>
<blockquote><p>
<font color=red>答案被接受</font><br>回复者:BigJames 回复日期:2003-11-21 14:05:32
<br>内容:对阿,socket可以设置成为阻塞方式、也可以设置成为非阻塞方式。<BR>阻塞方式的send,在数据全部发送完,才会返回控制;如果发送buffer不够,会一直等待下去。<BR>非阻塞方式的send,会立即返回,如果发送buffer不够,会返回已经发送的字节数,如果buffer已满,会返回一个错误码:大致是什么WSAEWOULDBLOCK(windows平台上)<BR>recv也会根据socket的是否阻塞,以两种不同的行为工作。<BR><BR>Clear?
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
<hr size=1>
<blockquote><p>
回复者:badboy 回复日期:2003-11-22 19:01:16
<br>内容:&nbsp;&nbsp;&nbsp;&nbsp;仍然凭感觉就知道您是网络方面的 高手,高手,高高高高……手!我确实已经开始有醍醐贯顶的感觉了!&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;师傅在上,受悟空一拜,不过,我资质愚钝,有些东西还要请师傅多多指教!<BR>&nbsp;&nbsp; “阻塞方式的send&nbsp;&nbsp;非阻塞方式的send” 您的意思是说,send函数只有一个,只不过,这个函数对于调用此函数的套接字是否是阻塞方式而有不同的表现。<BR>&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp; 
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
<hr size=1>
<blockquote><p>
回复者:BigJames 回复日期:2003-11-22 22:44:48
<br>内容:对的。send函数内部会对不同性质的socket进行分支处理。<BR>其实真正做工作的应该是系统内核处理的。<BR><BR>
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
<hr size=1>
<blockquote><p>
回复者:freeedom 回复日期:2003-11-23 00:14:00
<br>内容:又偷学到不少,呵呵~~
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
<hr size=1>
<blockquote><p>
回复者:badboy 回复日期:2003-11-24 15:21:39
<br>内容:BigJames 的话能让我“啃”挺长时间!比如:<BR>“标准的SOCKET,不包含同步功能,需要程序自己控制,在编程模式上,阻塞式的socket可以通过select达到一个进程/线程同时处理多个socket的目的。也可以用socket+thread的方式来做。”<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;“阻塞式的socket可以通过select达到一个进程/线程同时处理多个socket的目的。”这句话应该主要是对服务器说的吧!因为服务器要和多个客户同时保持连接状态。如果只用一个线程,那服务器对于各个客户来的所有消息都应该放在一个消息队列里,因为是阻塞模式,服务器的这个唯一的主线程会一个一个处理客户数据。如果没有处理完,是不会处理下一个客户的请求的。<BR>&nbsp;&nbsp;&nbsp;&nbsp; 我研究的这个聊天程序就是利用了套接字的阻塞模式和通过维护一个消息队列实现了多客户同步。(即所有和服务器连接的客户对服务器的请求的消息都会按先来后到的顺序放进服务器的消息队列中,等服务器有时间了,也会依照这个消息队列的顺序来处理各个客户的响应) 我估计是因为我的程序里各个客户之间的数据量很小,(就是聊天嘛)所以不需要用多线程来同步处理各个客户的数据。假如,我们这个程序支持数据传输。既客户A和B之间在传输一个很大的文件。而且,需要很长时间,那么服务器就需要专门用一个线程来处理这件事情。否则,其他客户会发现服务器始终在忙,而很长没有响应了!这个时候,就需要采用多线程模式了。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;不知道对不对? 请指教! 师傅!<BR>
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
<hr size=1>
<blockquote><p>
回复者:BigJames 回复日期:2003-11-24 15:51:51
<br>内容:不一定要多线程模式。<BR>下面是一个select的例子。<BR><BR>for(;;)<BR>{<BR>&nbsp;&nbsp;prv_ReFillFDSets();<BR><BR>&nbsp;&nbsp;int iRet = select(&amp;m_fsRead, &amp;m_fsWrite, &amp;m_fsExcept, &amp;m_timeoutVal);<BR><BR>&nbsp;&nbsp;if (iRet == 错误)<BR>&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp; return 错误码;<BR>&nbsp;&nbsp;}<BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;//下面处理m_fsRead.<BR>&nbsp;&nbsp;if (FD_IS_SET(&amp;m_fsRead, sockClientA)<BR>&nbsp;&nbsp;{<BR><BR>&nbsp;&nbsp;}<BR>&nbsp;&nbsp;else if (判断sockClientB)<BR>&nbsp;&nbsp;{<BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;}<BR>&nbsp;&nbsp;else if (判断sockClientC)<BR>&nbsp;&nbsp;{<BR><BR>&nbsp;&nbsp;}<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;//下面处理m_fsWrite.<BR>&nbsp;&nbsp;if (FD_IS_SET(&amp;m_fsWrite, sockClientA)<BR>&nbsp;&nbsp;{<BR><BR>&nbsp;&nbsp;}<BR>&nbsp;&nbsp;else if (判断sockClientB)<BR>&nbsp;&nbsp;{<BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;}<BR>&nbsp;&nbsp;else if (判断sockClientC)<BR>&nbsp;&nbsp;{<BR><BR>&nbsp;&nbsp;}<BR> <BR><BR>}<BR><BR>当客户A和B之间在传输一个很大的文件,需要很长时间,但是它们之间的通讯也是一个数据包一个数据包到达的。有点像分时系统那样,每一个客户都会得到机会去处理。<BR><BR>上述系统的缺点,就是必须的有一个机制来记录通讯session的状态,例如从客户A收到一个包,服务器知道是传给客户B的文件的一部分,而从客户C得到一个包,知道是给客户D的聊天包。等等。。。<BR><BR>不过上述模型需要对select有相当的了解。:)<BR>
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
<hr size=1>
<blockquote><p>
回复者:badboy 回复日期:2003-11-26 11:59:13
<br>内容:这个聊天程序的代码中,确实有select()这个函数,定义于下面这个函数中,(CClientSocket类是服务器用于管理客户端套接字的一个类,即所有和服务器连接的客户端套接字都是一个CClientSocket对象。)可是我把下面这个函数整个去掉,好象程序还是可以正常运行! 其实,下面这个函数根本就没有被任何服务器程序调用,(我用VC提供的find in files 工具在整个工程里查找的,但没有发现谁调用过这个函数。)我怀疑这个写程序的人多提供了一个没有用的函数。<BR>&nbsp;&nbsp; 如果上面我说的都对,那这个C/S程序可以不用select()了?<BR>&nbsp;&nbsp; <BR><BR>BOOL CClientSocket::HasConnectionDropped( void )<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;BOOL bConnDropped = FALSE;<BR>&nbsp;&nbsp;&nbsp;&nbsp;INT iRet = 0;<BR>&nbsp;&nbsp;&nbsp;&nbsp;BOOL bOK = TRUE;<BR>&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;struct timeval timeout = { 0, 0 };<BR>&nbsp;&nbsp;&nbsp;&nbsp;fd_set readSocketSet;<BR>&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;FD_ZERO( &amp;readSocketSet );<BR>&nbsp;&nbsp;&nbsp;&nbsp;FD_SET( m_hSocket, &amp;readSocketSet );<BR>&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;iRet = ::select( 0, &amp;readSocketSet, NULL, NULL, &amp;timeout );<BR>&nbsp;&nbsp;&nbsp;&nbsp;bOK = (iRet &gt; 0);<BR>&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;if(bOK){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bOK = FD_ISSET( m_hSocket, &amp;readSocketSet );<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;if( bOK ){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CHAR szBuffer[1] = &#34;&#34;;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iRet = ::recv( m_hSocket, szBuffer, 1, MSG_PEEK );<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bOK = ( iRet &gt; 0 );<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if( !bOK ){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;INT iError = ::WSAGetLastError();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bConnDropped = ( ( iError == WSAENETRESET ) ||<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;( iError == WSAECONNABORTED ) ||<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;( iError == WSAECONNRESET ) ||<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;( iError == WSAEINVAL ) ||<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;( iRet == 0 ) ); //Graceful disconnect from other side.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;return( bConnDropped );<BR>}<BR><BR><BR> 
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
<hr size=1>
<blockquote><p>
回复者:BigJames 回复日期:2003-11-26 13:05:41
<br>内容:这个函数的用途就是检查一下这个socket是否可用(通过select判断,然后再试着读一下,如果可读的话)。写的很是严谨,不过感觉上有些过度。客户端是否断掉,可以通过其他手段来判断。<BR><BR>这里用到的select,并不是用来支持多个socket并行监视的,而是一种测试socket的手段。光看这个select,并不能知道这个程序用什么手段来支持多个socket的。在其他地方没有select?你可以到其他类里面找一下,不会在Clientsocket里面定义的。<BR><BR>在windows下,还可以使用异步选择或者事件(Event)处理或者消息(Message)处理等方式去做服务器,select并不常用,他在Unix/跨平台程序上用得比较多。
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
<hr size=1>
<blockquote><p>
回复者:badboy 回复日期:2003-11-26 13:35:12
<br>内容:&nbsp;&nbsp;我用find in files&nbsp;&nbsp;和 alt F12&nbsp;&nbsp;两个工具来查找那个select()<BR>应该可以可以了吧!但,还是没有查到。实在没有办法了,这个源代码又发不到论坛上去,所以只能发到师傅的邮箱了。<BR>&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp; 您说的可以用<BR>1 异步选择 //这个就是用select() 吧?<BR>2 事件&nbsp;&nbsp;&nbsp;&nbsp;// 多线程方式<BR>3 消息处理&nbsp;&nbsp; // 这个是什么意思?<BR>&nbsp;&nbsp;那关于这个服务器到底应该怎么去选择?现在看来似乎有多种可选择方式。根据什么选择?<BR>&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp; 
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
<hr size=1>
<blockquote><p>
回复者:BigJames 回复日期:2003-11-26 14:07:28
<br>内容:我已经回信了。<BR>模式太多了,我都有点混了。<BR><BR>异步选择:见WSAAsyncSelect<BR>事件(Event): 见WSAEventSelect<BR>消息处理,呵呵,应该就是上面的WSAsyncSelect,都是通过窗口消息搞定的。<BR>再有就是select, 完成端口什么的(我也没有用过)。<BR>CSocket相关类的异步操作方式也算一种把。<BR>最后就是普通的阻塞式的标准SOCKET.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -