CSocket派生于CAsyncSocket类,是对Windows Sockets API的封装。CSocket可以与CSocketFile 和 CArchive 协同工作管理数据的发送和接收。对Windows Sockets API更高层次上的抽象使得网络编程逻辑关系更加清晰。同Windows Sockets API一样,CSocket也可以使用阻塞和非阻塞模式。本人用socket编程较少,对Windows Sockets API仅限于了解的水平,希望通过CSocket实现非阻塞模式解决近来遇到的一个问题。希望各位高手指出问题所在、与Win Sockets  API相比有什么不足,如果哪位高人能验证一下方案之可行性本人不胜感谢!好,言归正传。服务器端:
从CSocket派生两个类:
    1.class CListeningSocket : public CSocket。
    2.class CClientSocket : public CSocketCListeningSocket只有一个实例化对象,重载了OnAccept(),一旦有客户端接入,发送用户自定义消息到窗口程序,处理接入。
CClientSocket每接入一个客户端建立一个实例化对象,重载了OnReceive (),有数据进来时响应。CClientSocket类里面同时封装了
CSocketFile* m_pFile;
CArchive* m_pArchiveIn;
CArchive* m_pArchiveOut;
用于收发数据管理。窗口程序在收到CListeningSocket发来的消息以后
    1. 创建一个客户套接字m_pClientSocket=new CClientSocket
    2. 建立与客户端的连接m_pListenSocket->Accept(*m_pClientSocket)
    3. 初始化客户套接字,包括CSocketFile对相等
    4. 加入连接列表 m_connectionList.AddTail(m_pClientSocket);
    
客户端:
从CSocket派生class CSvrSocket : public CSocket
重载OnReceive(),同样封装CSocketFile等。客户端连接时,创建服务器套接字对象CSvrSocket * pSvrSocket = new CSvrSocket;
然后连接,连接成功后pSvrSocket加入连接列表m_svrConnectionList(多机互为服务器和客户机)数据发送:
从CObject派生一个消息类class CMsg:public CObject,为的是支持Serialize。
从客户端向Server发:
    1. 找到对应的pSvrSocket
    2. msg.Serialize(*pSvrSocket->m_pArchiveOut);
从服务器向客户端发找到对应的pClientSocket就可以了。数据接收:
这就比较方便了,无论哪个服务器或者客户端收到数据,与之对应CSocket对象的OnReceive()就会响应的。这样网状的网络连接估计能够承载多大规模的网络连接呢,是不实现了非阻塞模式。小规模的试验倒是比较理想,多了会怎样?有经验的大侠指点一下。

解决方案 »

  1.   

    我用CAsyncSocket做的,做法跟lz的差不多。
    我们的客户大概有10万人左右,做的是软件登入,登入后基本就不用管了,现在还不用keep alive。
    每次同时登入客户估计上限为100人次,我软件最大连接设为128,多了就挤掉最早建立连接的,当然客户感觉不到被挤掉,如有必要,会自动重连。
    服务器已经工作一个月了,客户端软件还在不断更新中,同时登入也就几十个是没有任何问题,多了工作也不知道效率如何,也正在测试中。
    我开始也在考虑CAsyncSocket的效率问题,毕竟客户数是不断变化的,可能会有新的需求。但是如果自己完成socket封装要写一个比库函数还要效率的应该不容易,如果有人能提供更好的机制那就太好了!
      

  2.   

    几10个没有问题,我试过同样的模型,在本机开服务端,客户端
    客户端开了近100个,机器还在跑估计要注意的就是客户端的那个做响应时,估计运算时间,即占用CPU的时间,不能过长要是在不同的机器中测试,可能就要好一些。另外就是要重新设置全部操时,根据你的程序要求。即便是和默认值相同,也需要重设一次,做为备注了解。唯一问题,服务器端如何断线重连。
      

  3.   

    学习,虽然也常用CSocket,但是还没有测试过100以上的
    最多只测试几十个,也是正常的
      

  4.   

    csocket的性能是没问题的
    就是不要让它跨越线程
    一个socket的发送和接受要在同一个线程
    否则会很慢
      

  5.   

    只有客户端需要断线重连
    服务器关闭客户端socket后,客户端的socket就会被reset,此时socket已经invalid了,需要调用create重新建立socket,再次connect。
    如果你的客户端与服务器的通信数据量很少,数据包间也没有先后依赖关系,可以采用无连接方式以提高效率,无连接时上面的过程就不再合适了,要自己维护客户端的连接信息(无连接的连接信息这并不矛盾,指的是客户端IP,端口等信息)。
      

  6.   

    IOCP的模式比楼主这种性能强很多,尤其在多客户端情况下。具体原理和思路,有时间的话请研究这个例子。http://www.codeproject.com/KB/IP/iocp_server_client.aspx
      

  7.   


    IOCP最多能连接多少客户端 ?
      

  8.   

    简单看了一下你推荐的IOCP,它解决了一客户一线程模式,节约了大量资源。用几个I/O worker线程管理多客户的输入输出。
    客户管理的逻辑关系上是不是要稍复杂一些,性能提高主要表现在哪些方面呢,里面提到了线程挂起(The threads are suspended, and don't use the CPU cycles until there is something to do.)。还有对网络资源应用效率方面的优势呢?
      

  9.   

    学习下了 很不错的问题 www.codeproject.com
    这个网站上的代码 我怎么都下载不了?
    谁知道原因
      

  10.   

    CAsyncSocket单线程百把个是没有问题的(这个没有做过测试),多线程+异步模式的话千把个不在话下(我测试最多是2000个)
      

  11.   


    检查断线通过API接口返回值就可以判断,但是不管API如何对于程序而言最直接的方法是客户端没有等到期待服务器端的响应。
    客户端非阻塞模式过程如下:
    1、启动服务请求;
    2、客户端保存服务请求状态;
    3、设置超时定时器;
    4、向服务器发送服务请求;

    5.1、如果在规定时间内收到期待服务消息,删除定时器,处理服务信息;
    5.2、超时处理,有可能需要重连了
    6、重置请求状态。客户端的异常分支做简单处理就可以了,没必要对每个分支都做很复杂的操作,大不了重新启动客户端,网络状况正常是软件正常运行的前提,服务器端才要求比较严格,所以对客户端断线这种问题实际上没那么复杂,因为网络本身是一个不可靠的连接,有没有断开是一个主观判断值,有时候1秒没响应算断开,有时候5秒没响应那也有可能是正常状况。
      

  12.   

    tcp协议通信建立过程要三次握手
    connect是一个独立的过程,连接过于频繁会增加服务器压力,两次连接中间时间要设置长度减轻服务器压力。
    连接好好的就没有必要断开,断开并不能增加容量,容量只和实际通信量有关。一般地,客户端socket有效都没有必要重新连接,发送返回正常都没有必要去重新连接,把socket状态交给系统去维护;socket被关闭或网络已经down,从socket是可以读到这个状态的,这时一般要重连,是否多次重连这这按需求定;socket状态正常而服务器端没有消息响应,可以选择重新发送请求消息,或者用户网络异常,或者根本就是服务器工作不正常。也就是说socket状况异常时才重连接,否则重连接一般都不能解决问题。
      

  13.   

    Windows Socket五种I/O模型——代码全攻略(一)(转)
    http://hi.baidu.com/xyh2007/blog/item/7f2ebf3de1e69e07bba1674e.html
      

  14.   

    你使用CSocket的思路不正确CSocket是针对阻塞模式优化的,标准用法是开子线程用CSocket进行阻塞IO你的服务器端应该写两个工作线程,一个负责收,一个负责发,其中负责收的子线程需要使用自定义消息将收到的内容发送到主线程当你的主线程需要收时,开子线程去收,需要发时也开子线程去发,CSocket对象指针可以直接作为参数传递给子线程,所谓的CSocket对象不能跨线程,那是胡扯的,具体细节可参考:
    http://blog.csdn.net/fangle6688/archive/2006/07/27/986808.aspx
    你目前的方案,从你的表述来看,既然你将CSocket设置成了非阻塞的
    你的发送逻辑就有问题,当IO频繁时,你直接调Send函数发送会失败,你至少还需要重载OnSend
    当然,实际上OnClose也需要重载,问题没有你想象的那么简单
      

  15.   

    回楼上,资料介绍CSocket是针对阻塞模式的,但是也说重载CSocket类是可以实现非阻塞模式。我用的都是重载CSocket类的,不知道是否真正能够实现非阻塞模式。
    现在我所有的试验都是在一个线程下做的,还没有试验将CSocket对象传到子线程里面处理的情况。我再试验一下CSocket跨线程的情况。
    服务器端OnReceive()重载了,OnSend没有,直接系列化出去的,这是直接由CSocketFile与CSocket关联的,没有直接使用CSocket类的Send函数。
    我就是不知道我这样做会产生什么样的结果,谢谢您的意见。少量的没有问题,连接多了以后呢?我怎么试验一下我的方案呢?
      

  16.   

    对CSocket的应用有不同意见了,哪位高人还有什么看法?关于CSocket和CSocketFile的关系还不清楚,是不是要分析一下CSocket从CAsyncSocket派生后的代码?哪位有类似的应用经验或者相关资料,给介绍介绍?
      

  17.   

    现在的问题是CSocket的发送过程还是不清楚,使用Serialize序列化向外发送数据看来只有通过实践来进行检验了。
    这贴我再顶一次,连续3次就不能自己顶了,也该结贴了。
      

  18.   


    Serialize实质上应该也是调用关联的CSocket对象的Send函数
    非阻塞的CSocket这样使用会出问题的子线程+阻塞模式,这才是CSocket的最优用法,特别是关联了CSocketFile,更应该如此
      

  19.   

    子线程+阻塞模式,这才是CSocket的最优用法,特别是关联了CSocketFile,更应该如此
    ====================================================================
    看来是这样的,我再找找资料。