2016-11-23 3 views
1

C++ 클라이언트에서 UDP 데이터 그램을 받아야합니다. 클라이언트가 올바르게 작동하고이 코드를 컴파일하는 IP에 데이터 그램을 보냅니다. 데이터 그램의 크기는 800Bytes입니다. 데이터 그램을 보내면 읽기 프로세스가 차단됩니다. 이 코드 다음 예제를 사용하여 만든 : https://en.wikibooks.org/wiki/Ada_Programming/Libraries/GNAT.Sockets_examples, 그리고 내 호스트에서 완벽하게 작동합니다. 어떤 생각?스트림 읽기 차단 UDP GNAT

procedure RECEIVE_DATA (
         DEST_UDP_PORT  : In WORD_TYPE; 
         SRC_UDP_PORT   : In WORD_TYPE; 
         WAIT_TIME  : In DURATION; 
         MESSAGE_ADDRESS : Out System.Address; 
         WAIT_RESULT  : Out Boolean 
         ) is 

task Receive is 
    entry Start; 
end Receive; 

task body Receive is 
    Address : Sock_Addr_Type; 
    Socket : Socket_Type; 
    Channel : Stream_Access; 
    Receive_Timeout : constant Duration := WAIT_TIME; 
    Offset : Ada.Streams.Stream_Element_Count; 
    Data : Ada.Streams.Stream_Element_Array (1 .. 800); 
begin 
    accept Start; 
    Initialize; 
    WAIT_RESULT := False;  
    Create_Socket (Socket, Family_Inet, Socket_Datagram); 
    Set_Socket_Option (Socket => Socket, 
         Option => (Gnat.Sockets.Receive_Timeout, Timeout => Receive_Timeout)); 

    Address.Addr := Inet_Addr(DEST_UDP_IP); 
    Address.Port := Port_Type(DEST_UDP_PORT); 
    Bind_Socket (Socket, Address); 

    Address.Addr := Inet_Addr(SRC_UDP_IP); 
    Address.Port := Port_Type(SRC_UDP_PORT); 
    Channel := Stream (Socket, Address); 

    loop 
     Ada.Streams.Read (Channel.All, Data, Offset); 
     exit when Offset = 0; 
    end loop; 
    Free (Channel); 
    Close_Socket (Socket); 
    WAIT_RESULT := True; 
    MESSAGE_ADDRESS := Data'Address; 

    exception when E : others => 
     Ada.Text_IO.Put_Line 
     (Exception_Name (E) & ": " & Exception_Message (E)); 
     WAIT_RESULT := False; 
     Free (Channel); 
     Close_Socket (Socket); 
end Receive; 

begin 
    Initialize (Process_Blocking_IO => False); 
    Receive.Start; 
    Finalize; 
end RECEIVE_DATA; 

답변

3

GNAT.Sockets.Receive_Socket을 사용해 보셨나요? 스트림은 TCP와 함께 작동하므로 데이터 그램을 스트리밍 할 수 없습니다.

예 :

클라이언트 :

with Ada.Streams; 
with Ada.Text_IO; 

with GNAT.Sockets; 

procedure UDP_Client is 
    use GNAT.Sockets; 
    Address : Sock_Addr_Type; 
    Socket : Socket_Type; 
    Data : constant Ada.Streams.Stream_Element_Array (1 .. 512) := (others => 42); 
    Last : Ada.Streams.Stream_Element_Offset; 
begin 
    Address.Port := 50001; 
    Address.Addr := Inet_Addr ("127.0.0.1"); 
    Create_Socket (Socket, Family_Inet, Socket_Datagram); 
    Send_Socket (Socket, Data, Last, Address); 
    Ada.Text_IO.Put_Line ("last :" & Last'Img); 
end UDP_Client; 

서버 :

with Ada.Streams; 
with Ada.Text_IO; 

with GNAT.Sockets; 

procedure UDP_Server is 
    use GNAT.Sockets; 
    Server : Socket_Type; 
    Address, From : Sock_Addr_Type; 
    Data : Ada.Streams.Stream_Element_Array (1 .. 512); 
    Last : Ada.Streams.Stream_Element_Offset; 
    Watchdog : Natural := 0; 
begin 
    Create_Socket (Server, Family_Inet, Socket_Datagram); 
    Set_Socket_Option 
    (Server, 
     Socket_Level, 
     (Reuse_Address, True)); 
    Set_Socket_Option 
    (Server, 
     Socket_Level, 
     (Receive_Timeout, 
     Timeout => 1.0)); 
    Address.Addr := Any_Inet_Addr; 
    Address.Port := 50001; 
    Bind_Socket (Server, Address); 
    loop 
     begin 
     GNAT.Sockets.Receive_Socket (Server, Data, Last, From); 
     Ada.Text_IO.Put_Line ("last : " & Last'Img); 
     Ada.Text_IO.Put_Line ("from : " & Image (From.Addr)); 
     exception 
     when Socket_Error => 
      Watchdog := Watchdog + 1; 
      exit when Watchdog = 10; 
     end; 
    end loop; 
end UDP_Server; 
+0

GNAT.Sockets.Receive_Socket가 차단됩니다 방금 읽은 좋아 과정. –

+0

다음은 간단한 UDP 클라이언트/서버의 예입니다. –

+0

예. 버클리 소켓 용어에서 "Stream"= TCP 및 "Datagram"= UDP. –