我用clientsocket控件 写了一个客户端程序,定时向客户端发送当前时间的字符串
用serverSocket控件 写了一个服务器程序,接收到客户端的数据后,把数据原样发送回去。我打开了10个左右的客户端程序,每隔1秒,向服务器发送数据,服务器收到后,发送回来。经过测试发现以下问题:1.clientsocket 客户端 有时会无端断开。
2.serversocket 服务器端 测试一个上午后,出现问题。客户端发送的数据,部分没有返回,有的几条数据一起返回(这个应该是网络问题)3.serversocket 服务器端 显示的连接数不准确,我所有客户端连接断开后,仍然显示有62个连接
4.serversocket 服务器端 最严重的问题,服务器端运行了一天,第二天客户端连接时连接不上了。我把程序贴出来,请高手指点,谢谢先。

解决方案 »

  1.   

    点击运行键 启动程序如下
    procedure TForm1.runClick(Sender: TObject);
    begin
      ServerSocket1.Port := StrToInt(Edit1.Text); //设置端口号
      if ComboBox1.ItemIndex = 0 then
        ServerSocket1.ServerType := stThreadBlocking  //实际未用
      else
        ServerSocket1.ServerType := stNonBlocking; //异步方式
      try
        ServerSocket1.Active := True;
      except
      end;
      run.Enabled := False;
      stop.Enabled := True;
    end;//停止程序
    procedure TForm1.stopClick(Sender: TObject);
    begin
       ServerSocket1.Active := False;
       run.Enabled := True;
       stop.Enabled := False;
    end;
    //连接上程序
    procedure TForm1.ServerSocket1ClientConnect(Sender: TObject;
      Socket: TCustomWinSocket);
    begin
       //判断连接数
        StatusBar1.SimpleText := 'connections '+ IntToStr(serversocket1.Socket.ActiveConnections);
        Timer1.Interval := 100;     //100ms
        Timer1.Enabled := True;         //定时
    end;
    //断开程序
    procedure TForm1.ServerSocket1ClientDisconnect(Sender: TObject;
      Socket: TCustomWinSocket);
    begin
      StatusBar1.SimpleText := 'connectioss '+ IntToStr(serversocket1.Socket.ActiveConnections);
    end;//接收  读数据程序 并发送
    procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
      Socket: TCustomWinSocket);
    var
      str1 : string;
      i : integer;
    begin
      str1 :=  Socket.ReceiveText;
      Memo1.Lines.Add(str1);
      Edit2.Text := IntToStr(StrToInt(Edit2.Text)+1);
      if StrToInt(Edit2.Text) > 200 then
        memo1.Lines.Delete(0);     //删除最早的一条
      //判断是哪一路的连接
      for i:=0 to serversocket1.Socket.ActiveConnections-1 do
        if   serversocket1.Socket.Connections[i].sockethandle=socket.SocketHandle then
        begin
          serversocket1.Socket.Connections[i].SendText(str1); //发送接收的字符串
          break;
        end;
    end;
      

  2.   

    不是socket问题,是编程问题,看看代码就知道
      

  3.   

    4.serversocket 服务器端 最严重的问题,服务器端运行了一天,第二天客户端连接时连接不上了。 这个错误类型是 asynchronous socket error 10060
      

  4.   

    1.类似的ECHO断开的原因可能是由于在socket消息处理过程当中更新了UI(即操作了Memo1,Edit2等VCL控件)导致某些Socket消息被丢弃,而产生异常;
    2.有可能是因为在处理消息过程当中更新了UI导致消息重入或者丢失而遗漏;另外就是流协议的本质,会存在断包和粘包现象,属于正常的,建议在发送的时候使用定长数据,或者由前置的一小段定长数据(比如一个四字节或两字节的数据)表示或提示后续内容的长度,从而在接收端加以处理,然后对断包进行拼接,对粘包进行分割;
    3.还是可能因为消息丢失而导致的问题,当然也有可能是因为连接并没有真正断开(可以使用netstat -na -o)查看socket状态;
    4.分为两种情况,首先要找出是客户端无法连接服务器,还是服务器不接受客户端的连接;前者应该是类似问题3所说的情况,可以重启客户端机器或者换一台客户端机器测试一下,用于确认;如果是服务器出现问题,则有可能是服务器资源被消耗完了,应该可以用任务管理器看到服务器的内存使用状态,特别是未分页内存(核心内存)占用是不是过高(Win32平台极限值只有256MB).
      

  5.   

    代码的问题
    我觉得很大
    参考一下这段代码 client_record = Record
        CHandle: integer;
        CSocket:TCustomWinSocket;
        CName:string;
        CAddress:string;
        CUsed: boolean; //是否被使用
    session:array[0..CMax] of client_record; //定义一个记录型数组procedure TForm1.ServerSocket1ClientConnect(Sender: TObject;
      Socket: TCustomWinSocket);
    var
    i,j,n,k:integer;
    sAConnections:TConnectionsParam;
    begin
       connectok:=true;
       j:=-1;
       for i:=0 to sessions do
         begin
           if not session[i].CUsed then
             begin
                session[i].CHandle:=socket.SocketHandle;
                session[i].CSocket:=socket;
                session[i].CName:=socket.RemoteHost;
                session[i].CAddress:=socket.RemoteAddress;
                session[i].CUsed:=true;
                Break;
             end;
            j:=i;
         end;
       if j=sessions then
         begin
            inc(sessions);
            n:=sessions;
            session[n].CHandle:=socket.SocketHandle;
            session[n].CSocket:=socket;
            session[n].CName:=socket.RemoteHost;
            session[n].CAddress:=socket.RemoteAddress;
            session[n].CUsed:=True;
         end;
    end;procedure TForm1.ServerSocket1ClientDisconnect(Sender: TObject;
      Socket: TCustomWinSocket);
    var
      i:integer;
    begin
    for i:=0 to sessions do
       begin
          if session[i].CHandle=socket.SocketHandle then
            begin
               session[i].CHandle:=0;
               session[i].CUsed:=false;
               break;
            end;
       end;
    end;
      

  6.   


    谢谢您的回复!
    1.对于您说的UI问题,在程序中应该怎么避免这种情况,从我给的程序中可以看出这种隐患吗?
    2.客户端非正常关机(下班时,一台机器被我非正常关了),导致网络中断,服务器端                               serversocket1.Socket.ActiveConnections 会正常反应吗?
    如果不能,有什么办法可以让服务器端知道断开了。
    3.(可以使用netstat -na -o)查看socket状态
       见笑了,我不知道怎么看,netstat -na -o  在哪里看?
      

  7.   


    看了你给的代码,很不错的思路。但我的代码并没错啊,我的应用很简单,接收到直接原样发回去。没必要记录下来哪个client端连接。谢谢大家的回复。
      

  8.   

    支持僵哥
    NetStart是个命令行执行程序
    跟Dos似的
      

  9.   

    谢谢僵哥 1.对于您说的UI问题,在程序中应该怎么避免这种情况,从我给的程序中可以看出这种隐患吗? 
    2.客户端非正常关机(下班时,一台机器被我非正常关了),导致网络中断,服务器端                              serversocket1.Socket.ActiveConnections 会正常反应吗? 
    如果不能,有什么办法可以让服务器端知道断开了。