基本需求:
Client在内网,Server在公网。当Client连上Server后,Server由用户操作,可随时向Client发命令。Client实时执行完后返回结果给Server,Server处理并显示执行结果。以上过程希望通过SOAP实现,不知Delphi中可否实现异步SOAP或回调?还有一个半成品的思路:Client在一个心跳周期中问Server:我需要做什么?然后阻塞
Server不马上回答,直到用户指定了某操作了以后,才回答:你要做XXX。(这一步是否可以用线程中加WaitForSingleObject?)
Client收到这个回复,执行XXX操作,把结果送回服务器,并要求下一轮:“我需要做什么?”
若Server的回复超过了1个心跳周期,Client重复上述过程。Server也使用定时器清除过期的请求。当然如果SOAP可以做到Server随时调Client中的函数,上面的所有机制都不用了。不知道Delphi中的SOAP能否满足上述需求?

解决方案 »

  1.   

    阻塞是可以的.
    你在soap service建立一个需要返回值的函数,当client调用的时候,它会等待这个值,想当于阻塞,但是时间你需要把握一下.
    /****当然如果SOAP可以做到Server随时调Client中的函数*****/
    你把server和client角色对调一下即可.其他不知道.
      

  2.   

    首先是这个等待时间可能很长服务器都没有进行操作,客户端甚至可能会重启机器等
    除非你把客户端写成一个windows服务程序,一启动系统就向服务器发一个请求操作的信息
     不过担心这个会不太稳定。
      

  3.   

    to baiduan:
    把server和client角色对调的话,代码怎么写?因为Client永远在内网,Server是无法调用Client提供的Web Service的。。to dabaicai:
    我原文中有写“若Server的回复超过了1个心跳周期,Client重复上述过程。”
    不过想想这个好像也不好实现。不知怎么打断阻塞的函数。
    用 TThread.Terminate 的话是假的打断,到时候会积累很多空线程
    用 TThread.Abort 的话又太狂暴了,会资源泄漏思路又阻塞了,请高手指点。
      

  4.   

    问题确实不要解决首先,角色对调不好搞,因为客户端在内网,没有对外ip(不知道在客户端局域网内上网的服务器通过端口映射是否可以解决)其次,说一个大概方法:把客户端做成一个服务,每隔一段时间向服务器端发送请求操作的指令(发过后通过变量状态决定是否重复发),而服务器端根据读到的信息,用一个变量来记录变化(比如false),然后服务器端创建线程并挂起,当服务器端操作后(比如要客户端数据),唤醒线程,返回要求,客户端接到后再通过要求操作
      

  5.   

    to dabaicai:谢谢回复。端口映射技术上能解决,但作为一个产品,该方法不太适用。soap应该是函数式的调用。您所说的“唤醒线程,返回要求”我想从技术语言来说,好像只能waitforsingleobject来阻塞吧。如果是创建线程,也是即时返回的。
      

  6.   

    这样行不行?
    client 询问我做什么?
    server 将询问储存在缓冲里,返回默认值:等待。
    用户指定操作,server将缓冲里这个client的行为由等待替换为相应的值:你做这个好了;
    client 等待一段时间后询问:我做什么。
    server 查询缓冲,回答:哦,你做这个好了。
      

  7.   

    to baiduan:
    client 等待一段时间后询问:我做什么。 <== 这里有写问题
    这样就不实时了..
      

  8.   

    客户端:
    thread.OnExecute()
    {
    while true
    {
    idhttp.get('http://ip/?packetType=心跳包&cmd=我要做啥',60秒);
    }
    }
    这样既有心跳包的功能,又有领取命令的功能,频率很低,才60秒一次 
    服务端:
    idhttpsrvr.OnGet()
    {
    读取数据;
    waitforsingleobject(mutex.Handle,60);
    发送数据(Data);
    } Button1.Click()
    {
    准备好待发送的数据(&Data);
    SetEvent(mutex.Handle);//这时候waitfor能马上返回,数据发出去,客户端的get马上返回
    }
      

  9.   

    yun ,你居然想用ws做实时?
    我可以负责的告诉你,这种想法很失败。tcp的实时是阻塞来的,是建立在tcp的协议上的。
    你居然使用soap来做实时?
    做好一个及时的就不错了。要不你还是用select 或者iocp算了。
      

  10.   

    ws的实时好像很常见吧。把阻塞放在线程里,是indy提倡的做法。
    用idTCP已经做出来实时S->C / C->S了。
    select和iocp都是比较底层的模型。
    我认为http和soap都是应用层的协议,应该可以服务于select或iocp之上。
    但是http和soap的封装可能丧失了TCP的某些特性,比如说S->C主动发送。
    您看看楼上的楼上这样写有没有漏洞?
      

  11.   

    有连接才能阻塞,soap,http根本没有连接,你怎么阻塞?
    除非客户端建立一个通信服务,服务器像要发送命令则连接这个服务端口
    ,客户'听'到了这个命令立刻去做xxx。
    要不你去参考ajax?代码我看不懂,
    你的思路颠覆了我对ws的认识,
    我需要回去清醒一下。
      

  12.   

    web server肯定是不可以调用Client的函数的,只能是Client主动去请求,一般都是用心跳包
      

  13.   

    to baiduan:
    谢谢回复,你提到的几个我也有些迷茫,只能黑盒地看这个问题:
    httpClient中调get方法,在超时之前,是一直阻塞在那里的,做过实验。我觉得“http根本没有连接,你怎么阻塞”这个问题应该这样回答:Http没有连接,但TCP有连接。httpClient.Get阻塞是可能的。“除非客户端建立一个通信服务,服务器像要发送命令则连接这个服务端口”
    这句的解释可以用FTP的PORT模式来解释(相反的是PASV模式)。PORT模式之所以几乎被淘汰是因为服务器几乎无法发起连接到客户端。Ajax用XmlHttpRequest对象,搞不懂它是怎么通讯的,居然可以做到客户端被动接收Xml。期待高人指点。
      

  14.   

    Ajax也是客户端主动请求服务器的,所有的web程序都是客户端主动请求服务器的,客户端被动接收Xml不会吧?肯定搞错了
      

  15.   

    to Cassava(车超):
    我的理解也是这样的,但是实际上Ajax就能做到异步回调,我也很迷惑。
    下面贴一段ajax的典型代码,一起学习。
    =============================================/** XHConn - Simple XMLHTTP Interface - [email protected] - 2005-04-08        **
     ** Code licensed under Creative Commons Attribution-ShareAlike License      **
     ** http://creativecommons.org/licenses/by-sa/2.0/                           **/
    function XHConn()
    {
      var xmlhttp, bComplete = false;
      try { xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); }
      catch (e) { try { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); }
      catch (e) { try { xmlhttp = new XMLHttpRequest(); }
      catch (e) { xmlhttp = false; }}}
      if (!xmlhttp) return null;
      this.connect = function(sURL, sMethod, sVars, fnDone)
      {
        if (!xmlhttp) return false;
        bComplete = false;
        sMethod = sMethod.toUpperCase();    try {
          if (sMethod == "GET")
          {
            xmlhttp.open(sMethod, sURL+"?"+sVars, true);
            sVars = "";
          }
          else
          {
            xmlhttp.open(sMethod, sURL, true);
            xmlhttp.setRequestHeader("Method", "POST "+sURL+" HTTP/1.1");
            xmlhttp.setRequestHeader("Content-Type",
              "application/x-www-form-urlencoded");
          }
          xmlhttp.onreadystatechange = function(){
            if (xmlhttp.readyState == 4 && !bComplete)
            {
              bComplete = true;
              fnDone(xmlhttp);
            }};
          xmlhttp.send(sVars);
        }
        catch(z) { return false; }
        return true;
      };
      return this;
    }
    ============================注意 xmlhttp.onreadystatechange = function(){ ...
    这句话也可以将onreadystatechange指向另一个写好的函数。这样当onreadystatechange触发的时候,就跳到该函数,实现异步回调。不知道"Msxml2.XMLHTTP"是怎么实现它的。
      

  16.   

    Ajax也是客户端主动请求服务器的,所有的web程序都是客户端主动请求服务器的,客户端被动接收Xml不会吧?肯定搞错了
    是可以实现的。
    IE从 XXX.0 开始(忘记版本了 )就在内嵌了一个 XXX 器(忘记名字),有了这个小东西,Ajax 才能发挥自如, 如果用户更换浏览器为 XXX.0 - 1 版本,肯定 Ajax 是发挥不了作用的。