2017-02-01 4 views
0

J'utilise ce server pour recevoir plusieurs paquets de données d'un C++UDP Client. Lorsque j'ai besoin d'un paquet, j'envoie un Request en utilisant un Client UDP pour que le client C++ envoie le paquet. Quand je fais ce processus plusieurs fois, je manque certains paquets et cette erreur:`GNAT.SOCKETS.SOCKET_ERROR: [11]` Ressource temporairement indisponible

GNAT.SOCKETS.SOCKET_ERROR: [11] Resource temporarily unavailable

Je pense que peut causer parce que le client envoie le paquet avant que le serveur est à l'écoute, mais je ne suis pas sûr. Y a-t-il un moyen de le résoudre? Si c'est le problème, est-il possible de s'assurer que mon serveur est préparé avant que le client envoie le message UDP?

procedure RECEIVE_DATA (
          DEST_UDP_PORT  : In Integer; 
          SRC_UDP_PORT   : In Integer; 
          WAIT_TIME   : In DURATION; 
          MESSAGE_ADDRESS  : Out System.Address; 
          WAIT_RESULT   : Out Integer; 
          MESSAGE_SIZE   : Out Integer 
          ) 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 .. 10000); 

begin 
    Initialize (Process_Blocking_IO => False); 
    WAIT_RESULT := 0; 
    MESSAGE_SIZE := 0; 
    -- Create Socket 
    Create_Socket (Socket, Family_Inet, Socket_Datagram); 
    Set_Socket_Option (Socket => Socket, 
         Option => (Gnat.Sockets.Receive_Timeout, Timeout => Receive_Timeout)); 

    --Bind Address 
    Address.Addr := Inet_Addr(DEFINE_IP_ADDR.IP_BOARD_ADDRESS); 
    Address.Port := Port_Type(DEST_UDP_PORT); 
    Bind_Socket (Socket, Address); 

    Channel := Stream (Socket, Address); 
    -- Receive Socket 
    Ada.Streams.Read (Channel.All, Data, Offset); 

    -- Close socket 
    Free (Channel); 
    Close_Socket (Socket); 
    WAIT_RESULT := 1; 
    MESSAGE_SIZE := Integer(Offset); 
    MESSAGE_ADDRESS := Data'Address; 
    Finalize; 
exception when E : others => 
     Ada.Text_IO.Put_Line 
     (Exception_Name (E) & ": " & Exception_Message (E)); 
     WAIT_RESULT := 0; 
     Free (Channel); 
     Close_Socket (Socket); 
     Finalize;  
end RECEIVE_DATA ; 
+0

Je ne comprends pas pourquoi vous avez une tâche du tout; pourrait aussi bien intégrer le corps dans la procédure. Tout ce qu'une tâche peut faire, c'est courir le risque de manquer le message attendu. Est-ce que 'Receive_Data' est appelé avec des numéros de port différents? parce que, sinon, je configurerais le socket une fois et passerais le socket à 'Receive_Data'. 'Integer'Size' est 32, peut-être que vous voulez mettre à jour' Message_Size' par 'Offset' à la place! (et 'Offset' sera le nombre d'octets de 8 bits, de toute façon, rien à faire avec' Integer'). –

+0

Ok désolé, maintenant il est mis à jour. Oui, j'utilise la fonction pour être appelé avec des numéros de port différents. –

+1

Peut-être que vous devriez préparer le socket pour recevoir le message avant de demander au client de l'envoyer? Et, c'est une ** très très mauvaise idée ** de passer l'adresse d'un tableau déclaré sur la pile d'une procédure à l'appelant de cette procédure. –

Répondre

0

Faire le changement suivant

Address.Addr := Inaddr_Any; 

Ceci est l'adresse que vous recevez de: pas votre adresse. Définissez votre adresse lors de l'envoi et n'importe quand lors de la réception