-1

I know how my packet looks like. It has 6 header fields (1 byte each, each header has 8 fields) and then it has the payload (data).

I would like to build a raw packet in C or C++ (it should look the same I think).

Here's what I think I should do:

    unsigned char packet[11];

    packet[0] = (0x81); // first header with 8 fields
    packet[1] = (0x8c); // second header with 8 fields
    packet[2] = (0xfe);
    packet[3] = (0x84);
    packet[4] = (0x1d);
    packet[5] = (0x79);
    packet[6] = (0x96); // payload, the 'h' letter, masked
    packet[7] = (0xe1); // 'e'
    packet[8] = (0x71); // 'l'
    packet[9] = (0x15); // 'l'
    packet[10] = (0x91);// 'o'

Where, for instance, 0x81 is the first byte (I simply converted every field (bit) of my first header to hex).

And then, simply, I want to send it to server: send(sockfd, packet, sizeof(packet), 0) to send it.

Receiving and printing the response:

unsigned char buffer[1024];
if ((recv(sockfd, buffer, len, 0)) == 0)
    {
        if (errno != 0)
        {
            exit(1);
        }
    }

    int i;
    for(i = 0; i<len; i++)
        printf("%x ", buffer[i]);

Am I right?

mirx
  • 606
  • 1
  • 9
  • 21
  • Have you tried this? – Ed Heal May 05 '17 at 11:19
  • @EdHeal: Of course I've tried. But the thing is, t he response I'm getting from server is really strange. Also, I'm not sure if I can build packets like this: using simple chars and assign them hexes. – mirx May 05 '17 at 11:21
  • 1
    Do you really mean raw data packets? Or are you using TCP or UDP? Because your "packet" doesn't look like a valid packet for any network protocol I know since it contains no destination address. – David Schwartz May 05 '17 at 11:27
  • @DavidSchwartz: I use TCP sockets. It's just a websocket frame. – mirx May 05 '17 at 11:31
  • @DavidSchwartz: So, how should I modify it? – mirx May 05 '17 at 11:33
  • If you're implementing WebSockets(WS), you don't need raw sockets: WS are based on TCP, just use normal TCP sockets. – edmz May 05 '17 at 11:52

2 Answers2

1

Your code will not appear to be error-prone!

But a good practice would be:

const std::uint32_t BUFFER_SIZE = 11;

std::vector<std::uint8_t> buffer;
buffer.reserve(BUFFER_SIZE)

buffer = {0x81,0x8c.....};

send( sockfd,
      reinterpret_cast <const char*> ( buffer.data() ),
      static_cast      <int>         ( buffer.size() ),
      0
      );

Doing so, your code gets more optimized, and avoids possible leaks, using the std vectors.

May also benefit from taking a look at ZeroMQ, as an example of a ready-made, high-performance asynchronous messaging library, aimed at use in distributed or concurrent applications.

user3666197
  • 1
  • 6
  • 50
  • 92
Hanrellz
  • 21
  • 2
1

Other than mishandling the return value from recv, your code looks okay.

if ((recv(sockfd, buffer, len, 0)) == 0)
    {
        if (errno != 0)
        {
            exit(1);
        }
    }

A zero return indicates normal close of the connection. There's no reason to check errno if it returns zero.

A return value of -1 indicates an error. In that case, it does make sense to check errno.

A value greater than zero indicates that number of bytes have been received. Be aware that it is perfectly normal for recv to return fewer bytes than you asked it for. If you want to receive exactly some number of bytes, you must call recv in a loop.

TCP is a byte-stream protocol and has no idea where your "packets" (really, messages) begin and end.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
  • But if I send the data to the echo server, and I know that it should respond with the exact data I sent it, maybe I should modify the `recv` to `recv(sockfd, buffer, 11, 0)`, where `11` stands for the exact number of bytes I want to receive? If it's not the right method, how the libraries do this? – mirx May 05 '17 at 11:37
  • @mirx Read my answer. If you get a return value of, say, 1, then call `recv` again to receive 10 more. TCP doesn't know those 11 bytes are a message and has no way to "glue" them together except by luck. The number you pass to `recv` is just the maximum number of bytes to return (the size of the buffer). It will return fewer if it has fewer at that moment. – David Schwartz May 05 '17 at 11:39
  • Fine, I will implement `recv_count`. – mirx May 05 '17 at 11:41
  • 1
    *There's no reason to check errno if it returns zero.* There's not only no reason to check `errno` against zero if `recv()` returns zero, checking `errno` in that case is *wrong*. If `recv()` returns zero, it leaves the value of `errno` unchanged, so `errno`'s contents are unrelated to the result of the `recv()` call and can be anything. – Andrew Henle May 05 '17 at 11:53