最近想做一个C/S的通用服务器,在开发过程中,遇到一些问题,请大家给出出招,要分我可以另开贴给问题1、在常见的C/S体系中,用户端始终是用一个socket与服务器通讯还是每个信息传输过程都新建一个socket?问题2、我知道在一些C/S系统中,采用“心跳”来通知服务器用户在线,问题是:假设用户A整操作时掉电了,在服务器中会有一个A用户的socket处于“僵尸”状态,如果该用户在小于系统约定的“僵尸”检查周期内(假设服务器没30秒检查一次僵尸,用户在掉电20秒后又上线)重新上线,这时服务器中同时有2个该用户socket,一个socket正常返回心跳包,另一个一直无反应,服务器如何将这2个内容(IP地址、用户名、密码)完全一致的socket分开,只关闭错误的socket,正确的保持继续通讯;如果要限制每个用户只能有一个socket与服务器通讯,那么对于一个漫长的通讯,用户要长时间等待(比如传输10G文件到服务器并写入数据库操作),这显然不太合理问题3、如何回退数据库操作?假设有一个耗时操作,用户发送10G文件到服务器,并写入数据库,操作流程如下表示(字母代表该过程)
用户端:打开文件(A)-----发送数据(B)---------等待服务器的处理结果(C)
服务器端:接收文件数据(D)---------文件接收结束(E)--------------写入数据库(F)--------得到数据库处理结果(G)------发送处理结果(H)
如果用户端在C状态执行“取消”操作(太耗时,反悔了),此时服务器正执行F操作,这时该如何响应用户的撤销请求?此时,并不知道服务器的执行结果,也不知道数据写到何处,甚至可能该操作的表都没有关键字(就是个流水记录表)问题4、如何终止指定的线程正常C/S体系中,服务器是开新线程来和用户完成数据交换的,如果某个数据交换过程中用户端掉电,服务器中就会有一个僵尸线程,如何关闭这个僵尸线程?目前能想到的最好结果是:使用一个标识,线程在操作时 时时读取该标识的值,发现是终止操作,处理已经得到的数据,之后正常终止,但是,要是线程也僵尸了,就无法读取标识的值了,如何安全强制关闭指定的线程?

解决方案 »

  1.   

    用户发送10G文件到服务器,并写入数据库.. 太牛b了.. 没见过这么整的.. 问题1. 两种都可,关键看你需求如何. 比如http服务器conn-live=false,则客户每次请求完服务器响应完,closesocket。 每请求都要创建新sock来连接服务器. conn live=true表示一直保持连接.
      

  2.   

    一般C/S服务器都是TCP或UDP服务器,http有现成的 IIS和tomcat,不用考虑
      

  3.   

    还免费,收费的更多了apache,weblogic....
      

  4.   

    不是高手,随便说两句:
    1. 没做过,不过个人觉得一个用户一个SOCKET比较稳定,频繁的建立注销SOCKET也是不小的开销。
    2. 建立一个SOCKET管理员对象,统一对这些SOCKET进行管理,每一个SOCKET都有一个和客户一一对应的身份认证。如果有客户掉线,而在系统超时检测前又连接上来,则关闭该用户对应的SOCKET或继续使用该SOCKET.所有的SOCKET采用异步方式,防止你说的僵死。
    3. 数据库操作的回退可以采用事务机制,一般操作为:BeginTrans,Execute,CommitTrans/RollbackTrans(回滚),需要数据库支持。
    4. 强行终止线程会引起内存泄漏,一般线程或SOCKET都不会僵住的,只要采用异步就可以了。如果SOCKET出问题会在你访问SOCKET时报错,可以根据错误信息来判断是什么错误引起的(比如断网、网络繁忙等)。经常听到有什么线程池啦,SOCKET池啦,可惜都没实际做过,应该也是一种解决之道,特别是客户端比较多访问不是很繁忙,而服务端比较少的情况。
      

  5.   

    to kyotrue1、长连接还是短连接视需求而定,通信频繁就用长连接。
    2、心跳包一般是服务器发给客户端的,客户端用来判断连接是否存活,是否需要重连。服务器一般是采用超时机制,当一段时间客户端没有请求时就断开。
    3、可以利用数据库的回滚功能。
    4、参看问题2,让线程自己退出
    ------------------------------------------------------------------
    1、作为通用服务器,无法确定通讯的情况,可能这个系统不传输文件,竟是些小的数据处理(一条语句或消息),而在另一个体系中,每个传输过程都比较耗时,但是连接数量少
    2、“一段时间客户端没有请求”如何判断?请求是通过TCP发出的,心跳是UDP发出的,TCP和UDP是2回事,我可以收到心跳包,我无法证明此时TCP是否断线,要是断线重连,没断线也重连,服务器就危险了!“心跳包一般是服务器发给客户端的,客户端用来判断连接是否存活,是否需要重连”这句话的含义是一定在服务器上保持一个活连接,这样的话,如果上线用户都不干活(但都在线),服务器可能无法接收要干活的用户连接,另外,socket的问题没解决!!!
    3、作为服务器,在接受完数据后,进入数据处理流程了,此时他不会再接收用户的撤销请求,否则的话,他就不知道何时开始启动数据处理模块,因为他无法确定用户请求的到底何时是结束!
    4、新城不会挂起(相当于死机)?
      

  6.   

    我是新手,随意说点 ,错了请见谅1.无法预测的通讯,不知道可不可以计算单位时间内的连接次数或者发送的数据量
    2.把已连接的socket放到一起统一管理下,在接收到下个连接时去判断已存在的连接是不是有一样的,有就销毁前一个,新来的补进去
    3.服务器进入处理流程后,客户端发送取消操作码?还在处理过程中就取消操作直接回滚,处理完了就执行删除,然后返回给客户端取消操作的处理情况?
    4.不知道可以做个监控线程不?主线程跟辅助线程相互监控?
      

  7.   

    关于问题1、2,我给你提出一个解决方案,有些难度,但只要你能做出这个东西,那么,以后的物质都可以一马平川了。这是个中间件。
    使用UDP协议做运输层。
    即实现在UDP协议之上一个高级协议栈,解决UDP的问题,实现连接、包排序、超时重发、心跳、如果可能还可以加上“加密”和md5校验。最好支持两种模式:流模式和报文模式。背景技术需要:UDP协议socket、多线程并发同步、定时器实现等。
      

  8.   

    这里需要状态机机制。把操作序号化,功能化,状态化,就可以redo了。
      

  9.   

    我冲没遇到过这个问题,你连接池是怎么做的,跟这个有赶,有客户断掉,你的回调例程里会得到通知,一句删除客户的代码只是毫秒的时间,他在连接又会跟他分连接迟空间,你把问题搞的太复杂了,看看我的IOCP
      

  10.   

    1. 常见C/S结构中,用户端始终是用一个socket与服务器通讯还是每个信息传输过程都新建一个socket,前面也有人回答了,使用长连接还是短连接和具体的需求有关。一般来说:
        客户端登录服务器  ->  服务器监听并新开启socket与终端通信(同时查询已经登录的用户队列,如存在该用户,则关闭之前的连接)
             |                            |
           socket         --            socket
                                          |
                                插入到通信socket和用户信息队列2. 心跳是为了维持C/S通信,主要是防止在无通信数据时超时而掉线。所以当传输数据时,是不存在该问题的。
        心跳数据发送的间隔时间,和具体项目环境有关。例如在通过GPRS模块->移动网络->互联网->服务器,那么就必须要注意相关GPRS网络连接超时时间,心跳包发送时间应该要短于这个时间,否则仅仅设置服务器端的socket超时时间,是没有用的。
        客户端出现异常,重新登录时,可以查询已经登录的用户队列,查询效率的高低和你自己的设计有关。
        需要写入大文件,在传输的过程中不存在连接超时问题,服务器端的超时与否,是和你的程序实现的。写入就更不存在问题了,可采用异步操作。3. 用户回退问题
        数据库支持回滚。4. 如何终止指定的线程
        如果超时没有接收到用户的任何通信信息,线程自然退出。
        如果用户登录时,该用户存在于通信队列(终端系异常退出再登录),那么就需要终止为该用户开启的原通信线程,可在队列内保存该线程句柄。还可考虑加个mutex保护。
      

  11.   

    过了半年的帖子了?要想取消,发送数据包的时候内含控制信息。即可。如果是利用 WebService来做心跳,那可以参考B/S应用,比如论坛什么的,提供一个session的机制.
    客户端通信时,包含Session信息。服务器端 具备 Session超时清空机制。如果有至少几千个客户端并发与服务器端通信的话,应该…………抱歉,我没这方面经验,但感觉像是网站呢。
      

  12.   

    假设用户A整操作时掉电了,在服务器中会有一个A用户的socket处于“僵尸”状态,如果该用户在小于系统约定的“僵尸”检查周期内(假设服务器没30秒检查一次僵尸,用户在掉电20秒后又上线)重新上线,这时服务器中同时有2个该用户socket,一个socket正常返回心跳包,另一个一直无反应,服务器如何将这2个内容(IP地址、用户名、密
    -------------------------------
    疯子,这还要检测啊,用户掉线,会立即在回调里提示的,还等30秒查他状态,晕
      

  13.   

    经过探索,我发现了这个问题很严重
    你要开个线程循环检测SOCK状态.当连接一个SOCK,你都要循环检测一次SOCK,看有没相同的