Sending HEX,integers over TCP

Hello,
I wrote the following program to send commands to a camera over TCP. However so far I have only been able to receive a welcome message from this camera.

The camera expects a command in the following format:
4 bytes of a Hex (0xBA12A20C)
4 bytes integer (value=16),
4 bytes integer (body integer)
4 bytes integer (footer integer)

So i made a 16 byte array and initialized it with 4 bytes array for each part. Converted integers to byte array.

With no success on camera actually performing any of the commands, I am now wondering if my approach is incorrect or I am doing something wrong. Any comments/suggestions will be really appreciated.

thanks!
Nancy.

-----------client---------------------

#include <stdio.h> /* for printf() and fprintf() */
#include <sys/socket.h> /* for socket(), connect(), send(), and recv() */
#include <arpa/inet.h> /* for sockaddr_in and inet_addr() */
#include <stdlib.h> /* for atoi() and exit() */
#include <string.h> /* for memset() */
#include <unistd.h> /* for close() */

#include <cstring>
#include <stdarg.h>

#include <iostream>
#include <cstdlib>
#include <limits>
using namespace std;
#define RCVBUFSIZE 32 /* Size of receive buffer */



typedef unsigned char byte;

byte header[]={0xBA,0x12,0xA2,0x0C}; /*first part of the command*/


int sock; /* Socket descriptor */
struct sockaddr_in echoServAddr; /* Echo server address */
unsigned short echoServPort = 41000; /* Echo server port */
char *servIP; /* Server IP address (dotted quad) */
char *echoString; /* String to send to echo server */
byte echoBuffer[RCVBUFSIZE]; /* Buffer for echo string */
unsigned int echoStringLen; /* Length of string to echo */
int bytesRcvd, totalBytesRcvd; /* Bytes read in single recv()
and total bytes read */


int sendCommand(int body, int footer)
{

byte byteArray[16];

// copy header into byteArray's first 4 bytes
memcpy(byteArray,header,4);


int length=16;

//convert length,body & footer into byteArrays of 4 bytes each
//and initialize byteArray

byteArray[5] = length & 0x000000ff;
byteArray[6] = (length & 0x0000ff00) >> 8;
byteArray[7] = (length & 0x00ff0000) >> 16;
byteArray[8] = (length & 0xff000000) >> 24;


byteArray[9] = body & 0x000000ff;
byteArray[10] = (body & 0x0000ff00) >> 8;
byteArray[11] = (body & 0x00ff0000) >> 16;
byteArray[12] = (body & 0xff000000) >> 24;



byteArray[13] = footer & 0x000000ff;
byteArray[14] = (footer & 0x0000ff00) >> 8;
byteArray[15] = (footer & 0x00ff0000) >> 16;
byteArray[16] = (footer & 0xff000000) >> 24;


if (send(sock, byteArray, 16, 0) == -1) {


cout << "Received socket error %d on command Send\n" << endl;
return -1;
}
else
{
cout << "\n\ncommand Sent" << endl;
}


}

int main(int argc, char *argv[])
{

if ((argc < 1) || (argc > 2)) /* Test for correct number of arguments */
{
fprintf(stderr, "Usage: %s <Server IP> \n",
argv[0]);
exit(1);
}

servIP = argv[1]; /* First arg: server IP address (dotted quad) */

/* Create a reliable, stream socket using TCP */
if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
fprintf(stderr,"socket() failed");

/* Construct the server address structure */
memset(&echoServAddr, 0, sizeof(echoServAddr)); /* Zero out structure */
echoServAddr.sin_family = AF_INET; /* Internet address family */
echoServAddr.sin_addr.s_addr = inet_addr(servIP); /* Server IP address */
echoServAddr.sin_port = htons(echoServPort); /* Server port */

/* Establish the connection to the server */
if (connect(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0)
fprintf(stderr, "Connection failed");

/* Receive message from server*/
totalBytesRcvd = 0;


if ((bytesRcvd = recv(sock, echoBuffer, RCVBUFSIZE - 1, 0)) <= 0)
fprintf(stderr,"\n\nRecv failed or connection closed prematurely");

totalBytesRcvd += bytesRcvd; /* Keep tally of total bytes recv*/


printf("\n\nBytes Recv:\n%s", echoBuffer);



printf("\nNo:of Bytes Recv:%u",bytesRcvd);

sendCommand(3,2); //body, footer


close(sock);
exit(0);
}
-------------------------------------------------
Last edited on
Maybe try using unsigned int?

Or to ensure that your int is 4 bytes unsigned you could use uint32_t.

 
int sendCommand(uint32_t body, uint32_t footer);
Last edited on
Also, you might want to put your code in code tags [code] which automatically colour codes it.
Also your subscripts appear to be out here:

Subscripting an array begins ar 0 and ends at size - 1.


So:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
	byteArray[4] = length & 0x000000ff;
	byteArray[5] = (length & 0x0000ff00) >> 8;
	byteArray[6] = (length & 0x00ff0000) >> 16;
	byteArray[7] = (length & 0xff000000) >> 24;

	byteArray[8] = body & 0x000000ff;
	byteArray[9] = (body & 0x0000ff00) >> 8;
	byteArray[10] = (body & 0x00ff0000) >> 16;
	byteArray[11] = (body & 0xff000000) >> 24;

	byteArray[12] = footer & 0x000000ff;
	byteArray[13] = (footer & 0x0000ff00) >> 8;
	byteArray[14] = (footer & 0x00ff0000) >> 16;
	byteArray[15] = (footer & 0xff000000) >> 24;
Thanks for the reply.

Can't believe i made my array subscripts wrong! Thanks for catching that :)

I tried unsigned int as well, but still no go on the camera commands.

My approach of converting everything into a byte array before sending is correct?

thanks,
Nancy.
There could be a problem with byte order.

In fact you use a different byte order for your header from the rest of yout integers.

So I think maybe either you need to change the header byte order or the byte order of all your unsigned integers.

If you take this line here:
 
byte header[]={0xBA,0x12,0xA2,0x0C}; /*first part of the command*/


Notice it is putting the MOST significant byte into the LOWEST memory address?

But your unsigned int conversions do the opposite:

1
2
3
4
	byteArray[4] = length & 0x000000ff;
	byteArray[5] = (length & 0x0000ff00) >> 8;
	byteArray[6] = (length & 0x00ff0000) >> 16;
	byteArray[7] = (length & 0xff000000) >> 24;


See? In that the LEAST significant byte of the unsigned int ends up in the LOWEST memory address.

So I think either you need to change the header to:

 
byte header[]={0c0C,0xA2,0x12,0xBA}; /*first part of the command*/


Or change all your other converters like this:

1
2
3
4
	byteArray[4] = (length & 0xff000000) >> 24;
	byteArray[5] = (length & 0x00ff0000) >> 16;
	byteArray[6] = (length & 0x0000ff00) >> 8;
	byteArray[7] = length & 0x000000ff;


But don't change both :)
To add to Galik's response, network byte order is always big endian.

In general, you would do something like this:

1
2
3
const uint32_t length = 16;
const uint32_t buffer = htonl(length);
memcpy(byteArray + 4, &buffer, sizeof(buffer));

and so on.

Last edited on
Thanks guys, for the input on byte order. It worked!
Topic archived. No new replies allowed.