2012-11-24 2 views
0

나는 win apis를 호출하여 C#으로 IOCP 서버를 만들고 있습니다. 1 개의 스레드 연결을 허용하고 CPU 코어에 따라 작업자 스레드가 있습니다.IOCP 스레드 처리

내 문제는 다음 코드 단편을 기반으로 같은 데이터를 동시에 처리하려고하는 2 개의 스레드를 얻게되어 해결책이 무엇인지 또는이 문제가 무엇인지 알 수 있습니까?

public class WorkerThread 
    { 
     public void Worker(NetSharedData data) 
     { 
      IntPtr bytestransfer = Marshal.AllocHGlobal(sizeof(UInt32)); 
      IntPtr clientid = Marshal.AllocHGlobal(sizeof(UInt32)); 
      IntPtr poverlapped = Marshal.AllocHGlobal(sizeof(UInt32)); 
      Console.WriteLine("Worker thread running"); 
      while (true) 
      { 
       Marshal.WriteInt32(clientid, 0); 
       Marshal.WriteInt32(bytestransfer, 0); 
       if (SocketInvoke.GetQueuedCompletionStatus(data.completionport, bytestransfer, clientid, poverlapped, SocketInvoke.INFINITE) == true) 
       { 
         if (Marshal.ReadInt32(poverlapped) == 0) 
         { 
          //thread shutdown 
          Console.WriteLine("Worker thread shutdown"); 
          break; 
         } 
         Client client = data.Clients[Marshal.ReadInt32(clientid)]; 
         if (Marshal.ReadInt32(bytestransfer) != 0) 
         { 
          if (client.operationtype == SocketInvoke.FD_WRITE) 
          { 
           if (client.send_data.ispending_operation == true) 
           { 
            client.SendLeft((uint)Marshal.ReadInt32(bytestransfer)); 
            break; 
           } 
          } 
          if (client.operationtype == SocketInvoke.FD_READ) 
          { 
           if (!client.Recv((uint)Marshal.ReadInt32(bytestransfer))) 
           { 
            client.Close(); 
            break; 
           } 
           if (data.OnRecv(client) == true) 
           { 
            //SendLeft test 
           } 
          } 
         } 
       } 
      } 
     } 
    } 

/* 
//THIS IS A CODE SNIPPET THAT BELONGS TO THE ACCEPT THREAD CLASS 
*/ 

public virtual bool Recv(uint expected_data_transfer) 
     { 
      IntPtr pwsabuf; 
      IntPtr wsaoverlapped; 
      IntPtr bytes_recv = Marshal.AllocHGlobal(sizeof(int)); 
      IntPtr flags = Marshal.AllocHGlobal(sizeof(int)); 
      Marshal.WriteInt32(flags, 0); 
      set_total_transfer(SocketInvoke.FD_READ, expected_data_transfer); 
      pwsabuf = recv_data.rtn_wsabuffarray(recv_data.buffer, (uint)recv_data.bufflen); 
      wsaoverlapped = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SocketInvoke.WSAOVERLAPPED))); 
      Marshal.StructureToPtr(overlapped, wsaoverlapped, false); 
      SocketInvoke.FillMemory(wsaoverlapped, (uint)Marshal.SizeOf(typeof(SocketInvoke.WSAOVERLAPPED)), 0); 
      unsafe 
      { 
       setoptype(SocketInvoke.FD_READ); 
       if (SocketInvoke.WSARecv(Convert.ToUInt32(sock.Handle.ToInt32()), pwsabuf, 
        (uint)1, bytes_recv, flags, wsaoverlapped, (IntPtr)null) == SocketInvoke.SOCKET_ERROR) 
       { 
        if (Marshal.GetLastWin32Error() != SocketInvoke.WSA_IO_PENDING) 
        { 
         return false; 
        } 
        return true; 
       } 
      } 
      return true; 
     } 

또한 WSASend 및 WSARecv?를 사용하여 데이터의 부분 전송 또는 부분 수신을 얻을 수 있습니까?

+1

1) 이유는 무엇입니까? 관리되는 비동기 소켓 메소드를 사용하거나 C 또는 C++의 소켓 코드 전체를 수행하고 좋은 깨끗한 인터페이스를 통해이를 관리 코드에 표시하십시오. 2) 읽기 또는 쓰기 작업마다 고유 한 중첩 구조가 필요합니다. –

답변

4

1) 이유는 무엇입니까? 관리되는 비동기 소켓 메소드를 사용하거나 C 또는 C++의 소켓 코드 전체를 수행하고 좋은 깨끗한 인터페이스를 통해이를 관리 코드에 표시하십시오.

2) 코드가 불분명하기 때문에 여기에서 추측하고 있지만 ... 읽기 또는 쓰기 작업마다 고유 한 중첩 구조가 필요합니다.

3) 예 WSASend는 일반적으로 데이터 버퍼가 OS 페이지 크기보다 크고 잠긴 페이지 한도에 도달했거나 비 페이징 풀이 부족한 경우에만 데이터의 일부를 보내고 보낼 수 있습니다. 이런 일이 발생하면 복구 할 수있는 방법이 없습니다. 먼저 처리 할 수있는 연결 수에 제한을 두어 해당 상황에 처하지 않도록하십시오. 10 만 개의 연결을 처리 할 수 ​​있지만 보류중인 중복 된 작업의 수를 관찰하십시오.

4) WSARecv는 모든 TCP 읽기 작업과 마찬가지로 1 바이트와 제공된 버퍼 크기 사이의 임의의 값을 반환 할 수 있습니다. 0을 리턴하면 피어는 연결의 송신 측을 종료합니다.

5) AcceptEx를 사용하여 해당 수락 스레드를 제거하십시오. 전용 수락 스레드가 있으면 다른 스레드가 컨텍스트로 전환되고 하나의 프로그램 내에서 여러 포트에서 수신 대기하는 경우 확장에 실패합니다.