Windows

NAVIGATION
CATEGORIES
REFERRENCE
LINKS
  • Non-LineMode Protocol Sending and Receiving

    7 answers - 2918 bytes - related search similar search Add To My Delicious Add To My Stumble Upon Add To My Google Mark Add To My Facebook Add To My Digg Add To My Reddit

    PGP SIGNED MESSAGE
    Hash: SHA1
    I am experimenting with writing a program that does not rely on LineMode
    to send and receive data. The following procedure is attached to a
    server component:
    TriggerWriteDebug is my own event, which at this time only outputs text
    to a TMemo.
    Also, I plan on changing the code to except Network Byte numeric
    data, but for now I want to get this out of the way. :-)
    procedure (Sender: T; ErrCode: Word);
    var
    I: Integer;
    Buff: Array[0_MAX_BUFF - 1] of Byte;
    begin
    TriggerWriteDebug('DataAvailable() enter');
    if (TMySockServerClient(Sender).State <wsClosed) then
    begin
    I := ReadFully(Sender, @Buff, 5);
    end;
    TriggerWriteDebug('DataAvailable() exit.');
    end;
    ReadFully is another procedure I have written in hopes that I can then
    read an entire string, word, integer, what have you and read until I
    gather up enough data to continue (since I'm not using LineMode).
    function TMySockServer.ReadFully(Sender: T; Data: Pointer;
    BytesExpected: Integer): Integer;
    var
    Buffer: PChar;
    : Integer;
    Received: Integer;
    begin
    := 1;
    GetMem(Buffer, BytesExpected);
    while (BytesExpected 0) do
    begin
    Received := TMySockServerClient(Sender).Receive(@Buffer[],
    BytesExpected);
    if (Received 0) then
    begin
    := + Received;
    BytesExpected := BytesExpected - Received;
    end;
    end;
    TriggerWriteDebug(Buffer);
    Result := ;
    end;
    I have a couple of questions:
    When I output Buffer in the last lines of ReadFully(), if I have a
    client that sends "blah!" (which is five characters), the Memo has a
    non-displayable character (but shows up on the Memo as a black block)
    and then 'blah!'. So I'm not sure if I'm grabbing the string correctly.
    I hope with minimal changes that this procedure might also grab numbers
    without error, too.
    When my test client disconnects from the server, the server enters its
    ClientDataAvailable event and does not exit, which is why I have a "if
    (TMySockServerClient(Sender).State <wsClosed)" line in my
    ClientDataAvailable - I was hoping that I could detect whether or not
    the socket is still connected and only then try to read data. As of
    right now, it stays in DataAvailable and my server goes into an infinite
    loop. :(
    I realize the advantages of a LineMode = TRUE. I may just switch, but
    at the current time I'm just trying to learn more about sockets and
    building custom protocols in general.
    Does anyone have any advice for me to make these routines operational or
    more robust?
    Cheers,
    Wes
    PGP SIGNATURE
    Version: GnuPG v1.4.0 (MingW32)
    JnYB2ex9LdhMnuX+aaNszX0=
    =KZhv
    PGP SIGNATURE
  • No.1 | | 805 bytes | |

    ReadFully is another procedure I have written in hopes that I can then
    read an entire string, word, integer, what have you and read until I
    gather up enough data to continue (since I'm not using LineMode).

    Your ReadFully won't work. You must think event driven. When DataAvailable is triggered, you must
    read data but you can't loop waiting for so much data to come. If you have not received enough data,
    just get thereceived data into a buffer and return from the event handler. When the next
    DataAvailable is triggered, you append the next data read into your buffer, until you get enough
    data. Basically, that's what LineMode is doing, until it has received a complete line.

    In addition, you have a memory leak: you allocate memory and never free it.
  • No.2 | | 1638 bytes | |

    PGP SIGNED MESSAGE
    Hash: SHA1

    Francois Piette wrote:
    Your ReadFully won't work. You must think event driven. When DataAvailable is triggered, you must
    read data but you can't loop waiting for so much data to come. If you have not received enough data,
    just get thereceived data into a buffer and return from the event handler. When the next
    DataAvailable is triggered, you append the next data read into your buffer, until you get enough
    data. Basically, that's what LineMode is doing, until it has received a complete line.

    K. I understand what you're saying, which for me is a definite step
    up. That being said, when would I actually act on the data that I have
    received from the socket? If I have LineMode off, that means I have to
    either 1) look for a terminator or 2) accept <xmany bytes and then act
    on the information I have so far, correct?

    Again, as I've seen in archive here before, what happens if my
    information gets processed in two batches (packets)? When do I decide
    K, enough is enough, and continue on processing? Is TWSocket
    neccessarily fit for binary-type protocols like Napster/ICQ/WASTE/etc
    with variable-length packets?

    In addition, you have a memory leak: you allocate memory and never free it.

    Yeah, I noticed that. Thanks for bringing it to my attention. That's
    like the 12th Commandment or something (the 11th being "Thou shalt not
    divide by zero!") :-)

    Cheers,
    Wesley

    PGP SIGNATURE
    Version: GnuPG v1.4.1 (MingW32)

    J+PTuWNJUGU2Fr81e+YwSoI=
    =jsDA
    PGP SIGNATURE
  • No.3 | | 1326 bytes | |

    K. I understand what you're saying, which for me is a definite step
    up. That being said, when would I actually act on the data that I have
    received from the socket? If I have LineMode off, that means I have to
    either 1) look for a terminator or 2) accept <xmany bytes and then act
    on the information I have so far, correct?

    Correct. You can select either way. In anycase, don't forget that you may
    receive more data that what you want. course you have to keep the extra
    data into your buffer. For example, even if you send an integer (4 bytes) as
    length and then send the actual data in a separate send, you may well
    receive your count and your actual data in a single packet and a single
    DataAvailable event.

    Again, as I've seen in archive here before, what happens if my
    information gets processed in two batches (packets)? When do I decide
    K, enough is enough, and continue on processing? Is TWSocket
    neccessarily fit for binary-type protocols like Napster/ICQ/WASTE/etc
    with variable-length packets?

    Yes of course. What you talk about is not TWSocket specific. It is just that
    TCP/IP work like that. Specially, TCP is a stream oriented protocol. It is
    suitable for transmitting any kind of data using any kind of TCP/IP based
    protocol.
  • No.4 | | 859 bytes | |

    Hello Wesley,

    If I have LineMode off, that means I have to
    either 1) look for a terminator or 2) accept <xmany bytes and then act
    on the information I have so far, correct?

    yes

    Again, as I've seen in archive here before, what happens if my
    information gets processed in two batches (packets)? When do I decide
    K, enough is enough, and continue on processing? Is TWSocket
    neccessarily fit for binary-type protocols like Napster/ICQ/WASTE/etc
    with variable-length packets?

    Sorry I dont understeand what you asking here. You can send binary data
    of course but if you wants to use LineMode then you have to escape some
    bytes, otherwise you have to send some length byte/word/dword.

    You find on my site some additional demo file witch may help you.

    Rgds, Wilfried
    http://www.mestdagh.biz
  • No.5 | | 1788 bytes | |

    PGP SIGNED MESSAGE
    Hash: SHA1

    Wilfried Mestdagh wrote:
    >>Again, as I've seen in archive here before, what happens if my
    >>information gets processed in two batches (packets)? When do I decide
    >>K, enough is enough, and continue on processing? Is TWSocket
    >>neccessarily fit for binary-type protocols like Napster/ICQ/WASTE/etc
    >>with variable-length packets?


    Sorry I dont understeand what you asking here. You can send binary data
    of course but if you wants to use LineMode then you have to escape some
    bytes, otherwise you have to send some length byte/word/dword.

    I guess what I'm trying to say is that with a conventional program, you
    can initiate a send, then for example if you receive a certain packet
    type, read more for one operation (say receiving a file listing after
    asking the server for it) and then keep your program going.

    For me it is difficult to understand how to "packetize" a TCP stream and
    rebuild packets on the receiving side, and only read what I think is
    neccessary for a certain programmer-defined packet type (and then act on
    them) when not using LineMode and using the *event-driven model* ICS
    employs.

    It's easy with LineMode on - ICS only forwards the data on when it
    receives a delimeter. But when it's off, it seems as though anything
    other than file sends and receives (because you don't really act on the
    file stream, you just send or recieve its bytes) proves to be a
    difficult task.

    Can you share some insight?

    Cheers,
    Wes
    PGP SIGNATURE
    Version: GnuPG v1.4.0 (MingW32)

    6EHgR/41vE9lCLit6LQY2yg=
    =Hetw
    PGP SIGNATURE
  • No.6 | | 2258 bytes | |

    It's easy with LineMode on - ICS only forwards the data on when it
    receives a delimeter. But when it's off, it seems as though anything
    other than file sends and receives (because you don't really act on the
    file stream, you just send or recieve its bytes) proves to be a
    difficult task.

    If not using a delimiter, you must use a byte count. In any case, the receiver need to know how much
    data has been sent by the sender. TCP doesn't preserve boundaries: it send all data in the correct
    order, without error and only once. But it can split or merge data according to what is needed by
    the network layer.

    Most protocols use line mode (SMTP, PP3, NNTP, ) some use both : FTP and HTTP. FTP use two TCP
    connections: one for commands and one for data. command stream, it use line mode. data stream,
    it just send data. End of data is found because the stream is simply closed. HTTP use a single TCP
    stream, begin with line mode in his header and then switch to byte count for the document. Byte
    count is given in one of the header lines.

    So what do you have to do ? You have to design your own protocol, using line mode or not, it is not
    very important. What is important is that at any moment one side know what the other is trying to
    do.

    I understood that you don't want to use line mode. Perfect for me. Use a byte count. You can, for
    example build each of your message with 4 byte being a 32 bit integer that gives the number of data
    bytes that follow. Send is trivial. Receiving require a buffer where you append everything you
    receive. Each time you received something (DataAvailable event, then call Receive method), you
    check how many bytes you have received. If less than 4, you just do nothing more. If more than 4,
    then you received your count. You compare the count with the actual data received. If you have
    enough data, you trigger your own event, such as MessageReceived, passing the count of bytes and
    the pointer to the first byte into your buffer (You can also copy the data but if will be slower).
    When the event handler returns, you remove the count and the message data from the buffer, keeping
    the rest for the next round.
  • No.7 | | 2821 bytes | |

    Hello Wes,

    In addition to the advice of Francois is what I often do if designing a
    protocol that is both ascii data (for commands) and binary data packets,
    is to preceide the packet with a length in hexadecimal form (byte, word
    or dword). Wy ? Because if most of the data is ascii command then it
    make the readability better if you log the data for debugging purposes.

    Rgds, Wilfried
    http://www.mestdagh.biz

    Thursday, June 2, 2005, 12:37, Francois Piette wrote:

    >It's easy with LineMode on - ICS only forwards the data on when it
    >receives a delimeter. But when it's off, it seems as though anything
    >other than file sends and receives (because you don't really act on the
    >file stream, you just send or recieve its bytes) proves to be a
    >difficult task.


    If not using a delimiter, you must use a byte count. In any case,
    the receiver need to know how much
    data has been sent by the sender. TCP doesn't preserve boundaries: it send all data in the correct
    order, without error and only once. But it can split or merge data according to what is needed by
    the network layer.

    Most protocols use line mode (SMTP, PP3, NNTP, ) some use both : FTP and HTTP. FTP use two TCP
    connections: one for commands and one for data. command stream, it use line mode. data stream,
    it just send data. End of data is found because the stream is
    simply closed. HTTP use a single TCP
    stream, begin with line mode in his header and then switch to byte count for the document. Byte
    count is given in one of the header lines.

    So what do you have to do ? You have to design your own protocol, using line mode or not, it is not
    very important. What is important is that at any moment one side know what the other is trying to
    do.

    I understood that you don't want to use line mode. Perfect for me. Use a byte count. You can, for
    example build each of your message with 4 byte being a 32 bit
    integer that gives the number of data
    bytes that follow. Send is trivial. Receiving require a buffer where you append everything you
    receive. Each time you received something (DataAvailable event, then call Receive method), you
    check how many bytes you have received. If less than 4, you just do nothing more. If more than 4,
    then you received your count. You compare the count with the actual data received. If you have
    enough data, you trigger your own event, such as MessageReceived, passing the count of bytes and
    the pointer to the first byte into your buffer (You can also copy the data but if will be slower).
    When the event handler returns, you remove the count and the
    message data from the buffer, keeping
    the rest for the next round.

Re: Non-LineMode Protocol Sending and Receiving


max 4000 letters.
Your nickname that display:
In order to stop the spam: 5 + 4 =
QUESTION ON "Windows"

EMSDN.COM