#include <fstream>
#include<iostream>
#include<cstring>
using namespace std;
class Address {
public:
char addr[6];
Address() {}
Address(string address) {
size_t pos = address.find(":");
int id = stoi(address.substr(0, pos));
short port = (short)stoi(address.substr(pos + 1, address.size()-pos-1));
memcpy(addr, &id, sizeof(int));
memcpy(&addr[4], &port, sizeof(short));
}
};
enum MsgTypes{
JOINREQ,
JOINREPLY,
DUMMYLASTMSGTYPE,
HEARTBEAT
};
/**
* STRUCT NAME: MessageHdr
*
* DESCRIPTION: Header and content of a message
*/
typedef struct MessageHdr {
enum MsgTypes msgType;
}MessageHdr;
typedef struct en_msg {
// Number of bytes after the class
int size;
// Source node
Address from;
// Destination node
Address to;
}en_msg;
//class Testing{
void send(Address *myaddr, Address *toaddr, char *data, int size);
int main()
{
MessageHdr *msg=new MessageHdr();
size_t msgsize = sizeof(MessageHdr) + sizeof(Address) + sizeof(long) + 1;
msg=(MessageHdr *)malloc(msgsize*sizeof(char));
int id=233;
short port =22;
long heartbeat=1;
msg=(MessageHdr *)malloc(msgsize*sizeof(char));
string s=to_string(id)+":"+to_string(port);
string s1=to_string(id+1)+":"+to_string(port+1);
cout<<s<<'\n';
cout<<s1<<'\n';
Address *addr= new Address(s);
for (int i = 0; i < 6; i++)
cout << addr->addr[i];
Address *toaddr= new Address(s1);
msg->msgType = JOINREQ;
//cout<<(char *)msg->msgType;
memcpy((char *)(msg+1), addr, sizeof(addr));
memcpy((char *)(msg+1) + 1 + sizeof(addr), &heartbeat, sizeof(long));
send(addr, toaddr, (char *)msg, msgsize);
return 0;
}
void send(Address *myaddr, Address *toaddr, char *data, int size) {
cout<<"inside send"<<'\n';
en_msg *em;
//static char temp[2048];
em = (en_msg *)malloc(sizeof(en_msg) + size);
em->size = size;
memcpy(&(em->from), &(myaddr), sizeof(em->from));
memcpy(&(em->to), &(toaddr), sizeof(em->from));
memcpy(em + 1, data, size);
cout<<(char *)(em+1);
}
This is my program,in between I am trying to check the address what is being stored in my char array. but upon printing the array, it gives some strange output. two strange symbols after printing the value of s and s1.
I am trying to store the id:port in the char array of the address class, but looks without success. Please help
The code I am referring to for printing is in the main function. Approx ten lines down the main function.
For say, my id is 233 and port is 22, The address is 233:22 I want to retrieve back 233:22 and print it. How do I do that here?
Thanks in advance :)
The problem is in this line:
cout << addr->addr[i];
Since addr->addr is an array of char, each element will be printed as the character it represents. If you'd rather print the integer value of each, simply cast it to int first.
cout << static_cast<int>(addr->addr[i]); // or old-fashioned: (int)addr->addr[i];
Given the following code:
for (int i = 0; i <= 6; i++)
cout << addr->addr[i];
And given Address's constructor:
size_t pos = address.find(":");
int id = stoi(address.substr(0, pos));
short port = (short)stoi(address.substr(pos + 1, address.size()-pos-1));
memcpy(addr, &id, sizeof(int));
memcpy(&addr[4], &port, sizeof(short));
It's clear that you are printing the bytes that conform a number
addr->addr is a char array which contains two integer variables, one having two bytes (int) and the other having 2 bytes (short).
So, if the number is , lets say, 436, you are printing:
0xB4 0x01 0x00 0x00
<crazy char> SOH NULL NULL
You must understand what are you printing, or what you want to print in order to print it properly.
Note: The most popular setup is assumed here, which means:
Little Endian arquitecture
4-byte int
2-byte short
Update
How to get address and port back:
int address;
unsigned short port;
memset(&address, addr->addr, 4);
memset(&port, addr->addr+4, 2);
Related
So I want to send a char and a const char from the tcp client to the server, but the code I have below
This is the sender
struct packet {
char caseRadio;//1byte
const char* path;//4byte
};
packet* clientPacket = new packet;
string a = "C:\\Users\\Desktop\\Project phoneedge\\ForJen";
clientPacket->caseRadio = '1';
clientPacket->path = a.c_str();
int iSend1 = send(TCPClientSocket, (char*)clientPacket, sizeof(packet), 0);
This is the reciever
struct packet {
char caseRadio;//1byte
const char* path;//4byte
};
packet* clientPacket = new packet;
int iRecv = recv(sAccecpSocket, (char*)clientPacket, sizeof(packet),0);
cout << clientPacket->caseRadio << endl;
cout << clientPacket->path << endl;
I only receive the caseRadio's 1
the path throws a Unhandled exception at 0x7A8308F0 (ucrtbased.dll) in Barebonesserver.exe:
At some point the path printed out something like this
\source\repos\Barebonesserver\Debug\Barebonesserver.exe
(this is a part of the project folder path, just how?)
Send a const char * over TCP does not make sense. A const char * is only the address of a string in the memory of the sender process. It cannot magically point to something interesting in the reader process. Furthermore, sending a struct over the network is not reliable, because different compilation options could lead to different paddings in the structures.
You need to serialize your data. A common way would be to send:
a single char for caseRadio
a 16 bit integer in network order for the size of the character string
the bytes of the character string
Sender side (tests of iSend1 omitted form brievety):
...
string a = "C:\\Users\\Desktop\\Project phoneedge\\ForJen";
int iSend1 = send(TCPClientSocket, '1', 1, 0);;
int iSend1 = send(TCPClientSocket, htons(a.size()), 2, 0);
int iSend1 = send(TCPClientSocket, a.c_str(), a.size(), 0);
Reciever side (test omitted ibidem):
char caseRadio
uint16_t size;
char *data;
int iRecv = recv(sAccecpSocket, &caseRadio, 1, 0);
int iRecv = recv(sAccecpSocket, &size, 2, 0);
size = ntohs(size); // revert to host order...
data = new char[size];
int iRecv = recv(sAccecpSocket, data, size, 0);
string a{data, size};
delete[] data;
I'm trying to build a raw socket and I've built a structure to have every header : ETH, IP, etc.
I just started by assigning ETH field but when I run just this part of code, I get segmentation fault:
typedef struct Network_frame_test{
unsigned char dst_mac_addr[CONF_MAC_ADDRESS_SIZE];
unsigned char src_mac_addr[CONF_MAC_ADDRESS_SIZE];
struct ethhdr *ethh;
struct iphdr *iph;
struct udphdr *udph;
unsigned char buffer[ SIZE_BUFFER ];
} Network_frame_test;
int main(void)
{
Network_frame_test frame_test;
const unsigned char message[] = {'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a'};
int message_size = sizeof(message)/sizeof(message[0]);
printf("messge size : %d", message_size);
unsigned char* sendbuff;
printf(" message %.2x", message[0]);
memset(&sendbuff,0,43);
printf(" %d", 0);
for(int i=0;i<6;i++)
{
frame_test.dst_mac_addr[i] = message[i+6];
}
frame_test.ethh = (struct ethhdr *)(sendbuff);
for(int i=0; i<CONF_MAC_ADDRESS_SIZE; i++)
{
frame_test.ethh->h_dest[i] = frame_test.dst_mac_addr[i];
}
}
sendbuff is a pointer to a char, not allocated or anything. By using memset on its address, you set its value to 0, which means a null pointer. Later on you assign it to frame_test.ethh, and try to access it. I believe that is where you see the issue.
Why is sendbuff an unsigned char pointer and not simply of type
struct ethhdr?
Also, why is the memset used for 43 bytes? I'd change it to be the size of struct ethhdr.
After that, simeply use
frame_test.ethh = &sendbuff;
...
struct ethhdr srndbuff:
memset(&sendbuff, 0, sizeof(sendbuff));
...
frame_test.ethh = &sendbuff
...
If you have to use it with unsigned char, then:
#DEFINE SIZE 43 /* or sizeof(struct ethhdr) */
...
unsigned char sendbuff[SIZE];
memset(sendbuff, 0, SIZE);
...
frame_test.ethh = (struct ethhdr *)(sendbuff);
...
Hope that helps.
I use Visual Studio Micro C++ to program Arduino Mega1280 AVR.
I keep all my mixed types config parameters in a struct that is persisted in the 4096 Bytes EEPROM (in addition to other information saved in the EEPROM).
For every new program upload, I wish to check the new config against the EEPROM saved config, which I do byte by byte, updating only EEPROM bytes that differ.
My problem is that while the code compiles OK, (no errors/warnings) I do not get what I expect, and when reading the struct by bytes, I only get part of the expected info. I need help to make it work properly. Thanks.
Here is my simplified code:
#include <avr\eeprom.h>
#include <EEPROM.h>
#include <Arduino.h>
char configVersion[5] = "VS41";
unsigned int deviceID = 0xF0F0;
char deviceRev[5] = "ABCD";
char revDate[11] = "09-08-2014";
unsigned int dataArraySize = 150;
struct defineConfigs {
char configVersion[5];
unsigned int deviceID;
char deviceRev[5];
char revDate[11];
unsigned int dataArraySize;
byte mode;
byte refpage;
byte tolerance;
byte externalTrigger;
byte laserEnable;
}
configData=
{
{configVersion[5]},
deviceID,
{deviceRev[5]},
{revDate[11]},
dataArraySize,
1,
2,
0,
0,
0
};
unsigned int configBaseAddress=3840; //0x0F00
void Setup()
{
loadConfig(configBaseAddress);
}
void loadConfig(int configAddress) //EA
{
int s;
for ( s=0; s<sizeof(configData); s++) {
// Serial.println(*((char*)(&configData) + s),HEX); //Serial.print(","); //for testing
if (*((char*)(&configData) + s) == EEPROM.read(configAddress + s)) {
} else {
EEPROM.write(configAddress + s, *((byte*)(&configData) + s));
Serial.println(EEPROM.read(configAddress + s),HEX);
//read back for testing
}
}
}
Initialization of configData use uninitialized data
{configVersion[5]}
point on the first character after the array configVersion[0 ... 4]. This is not as you expect the litteral string "VS41".
You could check this printing configData.configVersion :
printf("%s\n", configData.configVersion);
Try to modify configData initialization like this :
struct defineConfigs {
char configVersion[5];
unsigned int deviceID;
char deviceRev[5];
char revDate[11];
unsigned int dataArraySize;
byte mode;
byte refpage;
byte tolerance;
byte externalTrigger;
byte laserEnable;
} configData = {
"VS41",
deviceID,
"ABCD",
"09-08-2014",
dataArraySize,
1,
2,
0,
0,
0
};
I want to receive bytes into conbuf.buffer. either of test 1 or test2 is ok. I am not seeing any value in printf statement. Am I passing in the pointer correctly? How do I allocate memory to a char pointer inside a struct.
typedef struct cBuf
{
int size;
char *buffer;
} cbuf;
class A
{
cbuf conbuf;
void test();
}
void A::test()
{
int buffersize = 20;
char buf[buffersize];
conbuf.buffer = (char *)malloc(buffersize * sizeof(char *));
// test 1
int n = socket.receivebytes(conbuf.buffer, buffersize);
// test 2
//int n = socket.receivebytes(buf, buffersize);
//strcpy(conbuf.buffer, buf);
printf("conbuf.buffer %s \n", conbuf.buffer);
}
this
conbuf.buffer = (char *)malloc(buffersize * sizeof(char *));
should be
conbuf.buf = (char *)malloc(buffersize * sizeof(char)); //allocate space for char not pointer to char. Your struct only has buf member not "buffer"
Use this:
conbuf.buffer = (char *)calloc( (buffersize * sizeof(char))+1,1);
since printf requires last char of string to be null terminated, this ensures it. But data received from network may already contain NUL in the middle. So instead of using printf you should use fwrite:
fwrite(conbuf.buffer,buffersize , STDOUT);
I'd suggest you to redirect it in a file and do a hex dump to see the output.
I need to convert an unsigned 64-bit integer into a string. That is in Base 36, or characters 0-Z. ulltoa does not exist in the Linux manpages. But sprintf DOES. How do I use sprintf to achieve the desired result? i.e. what formatting % stuff?
Or if snprintf does not work, then how do I do this?
You can always just write your own conversion function. The following idea is stolen from heavily inspired by this fine answer:
char * int2base36(unsigned int n, char * buf, size_t buflen)
{
static const char digits[] = "0123456789ABCDEFGHI...";
if (buflen < 1) return NULL; // buffer too small!
char * b = buf + buflen;
*--b = 0;
do {
if (b == buf) return NULL; // buffer too small!
*--b = digits[n % 36];
n /= 36;
} while(n);
return b;
}
This will return a pointer to a null-terminated string containing the base36-representation of n, placed in a buffer that you provide. Usage:
char buf[100];
std::cout << int2base36(37, buf, 100);
If you want and you're single-threaded, you can also make the char buffer static -- I guess you can figure out a suitable maximal length:
char * int2base36_not_threadsafe(unsigned int n)
{
static char buf[128];
static const size_t buflen = 128;
// rest as above