使用Ada套接字的TCP / IP:如何正确完成数据包? [英] TCP/IP using Ada Sockets: How to correctly finish a packet?

查看:96
本文介绍了使用Ada套接字的TCP / IP:如何正确完成数据包?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Ada的Sockets库实现Remote Frame Buffer协议,但是在控制发送数据包的长度时遇到了麻烦。

I'm attempting to implement the Remote Frame Buffer protocol using Ada's Sockets library and I'm having trouble controlling the length of the packets that I'm sending.

我遵循 RFC 6143 规范( https://tools.ietf.org/pdf/rfc6143.pdf ),请参见代码中的注释以获取章节编号...

I'm following the RFC 6143 specification (https://tools.ietf.org/pdf/rfc6143.pdf), see comments in the code for section numbers...

          --  Section 7.1.1
          String'Write (Comms, Protocol_Version);
          Put_Line ("Server version: '"
            & Protocol_Version (1 .. 11) & "'");

          String'Read (Comms, Client_Version);
          Put_Line ("Client version: '"
            & Client_Version (1 .. 11) & "'");

          --  Section 7.1.2
          --  Server sends security types
          U8'Write (Comms, Number_Of_Security_Types);
          U8'Write (Comms, Security_Type_None);


          --  client replies by selecting a security type
          U8'Read (Comms, Client_Requested_Security_Type);
          Put_Line ("Client requested security type: "
            & Client_Requested_Security_Type'Image);

          --  Section 7.1.3
          U32'Write (Comms, Byte_Reverse (Security_Result));

          --  Section 7.3.1
          U8'Read (Comms, Client_Requested_Shared_Flag);
          Put_Line ("Client requested shared flag: "
            & Client_Requested_Shared_Flag'Image);


          Server_Init'Write (Comms, Server_Init_Rec);

问题似乎是(根据wireshark的)我对各种写过程导致字节在套接字上排队而没有发送。

The problem seems to be (according to wireshark) that my calls to the various 'Write procedures are causing bytes to queue up on the socket without getting sent.

因此,正在发送两个或更多数据包的数据作为一个并导致格式错误的数据包。第7.1.2节和第7.1.3节将在一个数据包中连续发送,而不是分成两个数据包。

Consequently two or more packet's worth of data are being sent as one and causing malformed packets. Sections 7.1.2 and 7.1.3 are being sent consecutively in one packet instead of being broken into two.

我错误地认为从套接字进行'Read 读操作会导致传出数据被清除,但是

I had wrongly assumed that 'Reading from the socket would cause the outgoing data to be flushed out, but that does not appear to be the case.

我如何告诉Ada的Sockets库此数据包已完成,立即发送?

How do I tell Ada's Sockets library "this packet is finished, send it right now"?

推荐答案

要强调 https://stackoverflow.com/users/ 207421 / user207421 评论:

我不是协议专家,但根据我自己的经验, TCP(请参阅RFC793)经常被误解。

I'm not a protocols guru, but from my own experience, the usage of TCP (see RFC793) is often misunderstood.


问题似乎是(根据wireshark),我对各种 Write过程的调用导致字节在套接字上排队而没有发送。

The problem seems to be (according to wireshark) that my calls to the various 'Write procedures are causing bytes to queue up on the socket without getting sent.

因此两个或多个数据包的价值数据作为一个发送,并导致数据包格式错误。第7.1.2节和第7.1.3节将在一个数据包中连续发送,而不是分成两个数据包。

Consequently two or more packet's worth of data are being sent as one and causing malformed packets. Sections 7.1.2 and 7.1.3 are being sent consecutively in one packet instead of being broken into two.

简而言之,TCP不是面向消息的。

In short, TCP is not message-oriented.

使用TCP ,向套接字结果发送/写入套接字结果仅将数据追加到TCP流。套接字可以在一个或几个交换中自由发送,如果您要发送的数据很长,并且要在TCP之上实现面向消息的协议,则可能需要处理消息重构。通常,在消息末尾会添加一个特殊的字符序列。

Using TCP, sending/writing to socket results only append data to the TCP stream. The socket is free to send it in one exchange or several, and if you have lengthy data to send and message oriented protocol to implement on top of TCP, you may need to handle message reconstruction. Usually, an end of message special sequence of characters is added at the end of the message.


进程通过调用TCP和将数据缓冲区作为参数传递。 TCP将来自这些缓冲区的数据打包为段,然后在Internet模块上调用以将每个段传输到目标TCP。接收方TCP将数据段中的数据放入接收方用户的缓冲区中,并通知接收方用户。 TCP在用于确保可靠的有序数据传输的段中包括控制信息。

Processes transmit data by calling on the TCP and passing buffers of data as arguments. The TCP packages the data from these buffers into segments and calls on the internet module to transmit each segment to the destination TCP. The receiving TCP places the data from a segment into the receiving user's buffer and notifies the receiving user. The TCPs include control information in the segments which they use to ensure reliable ordered data transmission.

另请参见https://stackoverflow.com/a/11237634/7237062 ,引用:


TCP是面向流的连接,而不是面向消息的连接。它没有消息的
概念。当您写出序列化的字符串时,它的
只会看到无意义的字节序列。 TCP可以自由地将
分解成多个片段,并以这些片段大小的块形式在
处被客户端接收。由
负责在另一端重建整个消息。

TCP is a stream-oriented connection, not message-oriented. It has no concept of a message. When you write out your serialized string, it only sees a meaningless sequence of bytes. TCP is free to break up that stream up into multiple fragments and they will be received at the client in those fragment-sized chunks. It is up to you to reconstruct the entire message on the other end.

在您的情况下,通常会发送一条消息长度前缀。
这样,客户端首先读取了长度前缀,这样便可以知道
传入消息应该有多大。

In your scenario, one would typically send a message length prefix. This way, the client first reads the length prefix so it can then know how large the incoming message is supposed to be.

TCP连接似乎接收了不完整的数据 ,引用:


recv函数只能接收1个字节,您可能必须多次调用它才能获取整个有效负载。因此,您需要知道需要多少数据。尽管您可以通过关闭连接来表示已完成连接,但这并不是一个好主意。

The recv function can receive as little as 1 byte, you may have to call it multiple times to get your entire payload. Because of this, you need to know how much data you're expecting. Although you can signal completion by closing the connection, that's not really a good idea.

更新:

I还应该提到send函数具有与recv相同的约定:您必须在循环中调用它,因为您不能假定它将发送所有数据。尽管它可能始终在您的开发环境中起作用,但是这种假设会在以后给您带来麻烦。

I should also mention that the send function has the same conventions as recv: you have to call it in a loop because you cannot assume that it will send all your data. While it might always work in your development environment, that's the kind of assumption that will bite you later.

这篇关于使用Ada套接字的TCP / IP:如何正确完成数据包?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆