- I did an analysis of the event sequence that should take place in order to use a single process.
- I made some plans about how to create megaphone_tcp.
- Determine if segment contains a complete header
- If not, then keep reading until you do have a complete header
- Parse out the connection ID and packet length,
- If you have a complete header, then determine if you have a complete megaphone packet
- If not, then keep reading until you have a complete megaphone packet
- Send the megaphone process the completed packet.
- Wait for another packet to arrive.
- I created receive_loop, which takes care of controlling the process.
In today's report, I created receive_header
%
%% extract a complete megaphone header from the supplied data and from the
%% supplied socket if the data is not enough.
%%
%% This function attempts to combine any leftover data with any newly received
%% data. It then determines if it has enough data to form a complete megaphone
%% header. If it does then it extracts out the fields from the data according
%% the standard locations and returns them.
%%
%% If the function does not have enough data to form a complete megaphone
%% header, it will try to read more data from the supplied socket until it
%% receives a complete packet.
%%
%% Socket --- The TCP socket that should be used to get more data.
%% LeftOvers --- Any data that should appear before the Data parameter.
%% This value may be undefined if there was no left over data from the
%% previous packet.
%% Data --- Some newly received data from the socket. This should appear after
%% the leftovers from the previous packet, if any exist.
%%
%% Returns { Length, CID, Content } where Length is an integer that is the
%% number of bytes in the complete message, including the megaphone header.
%% CID is the connection ID of the connection, as a string (list). Content
%% is the content, if any is left over from the header. If there is no
%% data left over from the header, then his value is returned as undefined.
%%
receive_header(Socket, LeftOvers, Data) ->
Data2 = case LeftOvers of
undefined -> Data;
true -> LeftOvers ++ Data
end,
case byte_size(Data2) of
Length < ?PREFIX_LENGTH ->
case gen_tcp:recv(Socket, 0) ->
{ok, NewData},
receive_header(Socket, Data2, NewData)
end;
true ->
extract_CID_length_body(Data2)
end.
This function takes create of detecting when the system has not received a complete packet and therefore needs to wait for more data from the client. It uses the extract_CID_length_body function to extract out the data from the packet:
%% extract out the packet length, the connection ID and the packet contents
%% from a binary block of data.
%%
%% Binary --- this should be the binary representation of a megaphone packet
%% header. The binary may also contain the partial or complete contents
%% of a megaphone packet content.
%%
%% The function returns the tuple {Length, CID, Content} where Length is the
%% length of the complete packet, include the megaphone header. CID is the
%% connection ID as an integer value. Content is the megaphone packet contents.
%%
%% The input packet may contain no content or only part of the content of the
%% packet and may therefore have a value of undefine or it may be a binary
%% whose length is less than that of the complete content.
%%
extract_CID_length_body(Binary) ->
BinaryPacketLength = binary_part(Binary, ?PACKET_LENGTH_START, ?PACKET_LENGTH_LENGTH),
StringPacketLength = binary_to_list(BinaryPacketLength),
{ PacketLength, _ } = to_integer(StringPacketLength),
BinaryConnectionID = binary_part(Binary, ?PACKET_CID_START, ?PACKET_CID_LENGTH),
StringConnectionID = binary_to_list(BinaryConnectionID),
BinaryContent = binary_part(Binary, ?PACKET_CONTENT_START, byte_size(Binary) - ?PACKET_HEADER_LENGTH),
{PacketLength, StringConnectionID, BinaryContent}.
Next time, more functions that handle the extraction of packets.
No comments:
Post a Comment