首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > .NET >

关于winsock服务端接收数据很频繁时出现的有关问题

2013-07-01 
关于winsock服务端接收数据很频繁时出现的问题。我用的是阻塞的模式首先我监听起来 //初始化winsocksocket.

关于winsock服务端接收数据很频繁时出现的问题。
我用的是阻塞的模式

首先我监听起来

 //初始化winsock
socket...

//监听

然后用线程类 TThread创建一个Accept的 线程 线程里面whil循环,作为接受客户端的连接
当接受到客户端进来连接的时候 再创建一个线程(CreateThread)来recv客户端的数据

现在遇到的问题是 有N个客户端,并且客户端非常频繁的,向服务端发送数据的时候 服务端有时候会
漏掉一些数据 接收不到 是不是代码有问题?
我肯定客户端的发送操作是正确的。


//======Accept 线程==============================
TAcceptThread = Class(TThread)

TAcceptThread.Create(sock_Main);

//==============================Accept 线程==============================

constructor TAcceptThread.Create(ListenSock: Cardinal);
begin
   F_ListenSock := ListenSock;
   inherited Create(False);
end;
procedure TAcceptThread.Execute;
var
  chBuffer : array[0..9000] of AnsiChar ; //2K 缓冲区
  dwThreadID : DWORD;
  PMyPara:PMyParam;
  MyPara:MyParam;
begin
  while True do
  begin
     //等待客户端来连接
     //OutputDebugString('等待客户端来连接');
     F_RecvLogStr := '';
     F_cAddrlen := SizeOf(F_sockAddrClient);
     ZeroMemory(@F_sockAddrClient, F_cAddrlen);
     F_AcceptSock := accept(F_ListenSock, PSockAddr(@F_sockAddrClient), @F_cAddrlen);
     if INVALID_SOCKET = F_AcceptSock then
     begin
       F_RecvLogStr := 'accept error!';
       F_RecvLogStr := F_RecvLogStr + '  Error Code: ' + IntToStr(GetLastError) + FormatDateTime('yyyy-mm-dd hh:mm:ss:zzz',now);
       Sleep(500);;
       Continue;
     end;
     //客户端连接进入
     //保存IP地址
     F_ClienIPAddr := string(inet_ntoa(F_sockAddrClient.sin_addr));
     F_ClientSockStr := IntToStr(F_AcceptSock);
     F_RecvLogStr := F_RecvLogStr + '-----接收到一个连接-----' + #13#10 + F_ClienIPAddr + '       ' + FormatDateTime('yyyy-mm-dd hh:mm:ss:zzz',now) + #13#10;
     //显示日志
     Form1.mmo1.Lines.Add(F_RecvLogStr);
     new(PMyPara);
     PMyPara.MySock := F_AcceptSock;
     CloseHandle(CreateThread(nil, 0, @MyRecvThread, PMyPara, 0, dwThreadID));
  end;
end;


function MyRecvThread(lParam :PMyParam):DWORD;
var
  chBuffer : array[0..9000] of AnsiChar ; //2K 缓冲 足够矣
  cRecvBuffer : string;
  cRecvLogStr : string;
  cOrderStr : string;
  //Buff: String[100];

  addrIP : sockaddr_in;
  nLen   : Integer;
  F_IP : string;
begin
   //接收数据过程
     ZeroMemory(@chBuffer[0], 9000);
    //GetMem(chBuffer[1],2047);
    try
      if recv(lParam.MySock, chBuffer, 9000, 0) > 0 then


      begin
        cRecvBuffer := string(chBuffer);
        cRecvLogStr := string(cRecvBuffer);
        cOrderStr :=  cRecvLogStr;
        //===========保存接收数据到日志==============================
        cRecvLogStr := '-----START------------接收的数据------------------------'
                        +#13#10+cRecvLogStr+'  '+#13#10+
                        ' -----END--------------接收的数据------------------------'
                        +FormatDateTime('yyyy-mm-dd hh:mm:ss:zzz',now)+#13#10;
        //cRecvLogStr := 'aaa' + cRecvLogStr + #13#10;
        //cRecvLogStr := '-----START------------接收的数据------------------------' + #13#10 + cRecvLogStr;
          //获取对方的IP地址
        try
          nLen := SizeOf(sockaddr_in);
          if getpeername(lParam.MySock, addrIP, nLen) = 0 then
          begin
            F_IP := inet_ntoa(addrIP.sin_addr);
          end
          else
          begin
            F_IP := 'IP有错误!';
          end;
        except
        end;

        TSaveClienData.Create(lParam.MySock, cRecvBuffer, F_IP);

      end
      else
      begin
        //接收发生错误
        cRecvLogStr:='---------------Error Recv-----------------'+FormatDateTime('yyyy-mm-dd hh:mm:ss:zzz',now)+#13#10;
      end;
    finally
      //处理异常错误
      //显示日志
      Form1.mmo1.Lines.Add(cRecvLogStr);
    end;
    Result := 0;
end;





[解决办法]
请做以下检查:
  1)客户端发送有没有检查是否成功?(如:发1k,实际只发出900)


  2)服务器端接收,缓冲区是否足够?溢出有没有检查?
  3)客户/服务器端,有没有应用层协议?如果没有,应该定义应用层协议。 
  4)如果不是处理海量客户端,应该使用长连接模式。
  
 附:建议使用早期Delphi自带的Winsocket组件,很好用。需要特殊处理时,使用THackWinsocket.

热点排行