我在delphi用了Tsocket做服务器端通讯端口 ,它默认是阻塞方式,可是为什么阻塞不好用呢,接受一次连接后阻塞就不好用了呢,程序代码如下:
  wVersionRequested:=MAKEWORD(2,2);
  erro:=WSAStartup(wVersionRequested,wsd);
  if erro<>0 then
   WSACleanup;
  if (LOBYTE(wsd.wVersion)<>2) then
    WSACleanup;
  if(HIBYTE(wsd.wVersion)<>2) then
    WSACleanup;
  V_CONN_ID := socket(AF_INET,SOCK_STREAM,0);
  cmd:=0;
  rtn:=ioctlsocket(V_CONN_ID,FIONBIO,cmd);
  if(rtn<>0) then
   exit;
  if(V_CONN_ID=INVALID_SOCKET) then
   exit;
  ZeroMemory(@m_rcvaddr,sizeof(m_rcvaddr));
  ZeroMemory(@m_acceptaddr,sizeof(m_acceptaddr));
  m_rcvaddr.sin_family := PF_INET;
  m_rcvaddr.sin_addr.s_addr := INADDR_ANY;
  m_rcvaddr.sin_port := htons(strtoint(form1.listen_port));
  rtn:=bind(V_CONN_ID,m_rcvaddr,sizeof(m_rcvaddr));
  if(rtn<>0) then
   exit;
  rtn:=listen(V_CONN_ID,1);
  if(rtn<>0) then
   exit;
  while (not form1.rec_stop_flag ) do
  begin
    V_ACCEPT_ID:=accept(V_CONN_ID,m_acceptaddr,@m_accept_len);//???????
  end;

解决方案 »

  1.   

    //--一个线程处理Socket阻塞
    procedure SocketServerOp(p: Pointer); stdcall
    var
        s_server,s_client: TSocket;
        nameLength: Integer;
        server,client: sockaddr_in;  //tpye:sockaddr_in
        WSAData: TWSAData;
        procedure SelectSocket;   
        var
           ErrNum,nfds,iret:integer;
           setR:TFDSet;
        begin
           ErrNum:=1;
           while ErrNum<10 do
           begin
             nfds:=0;
             FD_ZERO(setR);
             FD_SET(s_server,setR);
             // 最后一位参数为nil表示阻塞直到有连接请求 iRet = select(iu, setR, nil, nil, timeout);
             iRet := select(nfds,@setR, nil,nil,nil);
             if iRet= SOCKET_ERROR then
                inc(ErrNum)
             else if iRet<>0 then break;
           end;
        end;
    begin
       while true do
       begin
         server.sin_family:=AF_INET;
         server.sin_addr.S_addr :=INADDR_ANY;
         server.sin_port:=htons(CommPort);
         if WSAStartup($101, WSAData)<>0 then exit;
         s_server:=socket(PF_INET,SOCK_STREAM,0);
         try
           if (s_server=INVALID_SOCKET) then exit;
           if bind(s_server,server,sizeof(server))<>0 then exit;
           if listen(s_server,20)<>0 then exit;
           nameLength:= sizeof(client);
           while true do
           begin
             SelectSocket;
             s_client:= accept(s_server,@client,@nameLength);
             if s_client=INVALID_SOCKET then exit;
             try
               //--处理过程
             except
               CloseSocket(s_client);
               CloseSocket(s_server);
               WSACleanup;
               break;
             end;
           end;
         except
           CloseSocket(s_server);
           WSACleanup;
         end;
       end;
    end;