TCP send struct not working Unhandled exception - c++

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;

Related

how to automatically null terminate char[] inside array

I have this code and I want for each char[] inside message struct will be null terminated in order to avoid print all the memory values. if I create a single element it poses no problem. but when I have several elements in a msg array when I null terminate the char and when I add a new element it seems to overwrite and the null terminate will disapear!
typedef unsigned char byte;
enum msgType {
tree = 2
};
struct header {
msgType _type;
unsigned _value;
};
struct message {
uint16_t x;
bool b;
char c[5];
};
void allocateHeader(int value, byte* buffer, int size) {
header* t = (header*)buffer;
memset(buffer, 0, size);
t->_type = tree;
t->_value = value;
}
int main() {
byte buffer[1000];
std::string str = "hello";
std::string str2 = "fooo";
allocateHeader(8, buffer, 20);
message msg1;
msg1.x = 18;
msg1.b = false;
memset(msg1.c, 0, 5);
memcpy(msg1.c, str.c_str(), 5);
msg1.c[5] = '\0';
message msg2;
msg2.x = 1;
msg2.b = true;
memset(msg2.c, 0, 4);
memcpy(msg2.c, str2.c_str(), 4);
msg2.c[4] = '\0';
message msg[2];
msg[0] = msg1;
msg[0].c[5] = '\0';
msg[1] = msg2;
msg[1].c[4] = '\0';
memcpy(&buffer[sizeof(header)], &msg, sizeof(msg));
message msgrecp[2];
message* msgp = (message*)&buffer[8];
for(auto i=0; i < 2; i++){
msgrecp[i] = *msgp;
std::string str(msgrecp[i].c);
std::cout << msgrecp[i].b << " " << str << " " << msgrecp[i].x << std::endl;
//print
//0 hello[|[#{[ 18
//1 fooo 1
msgp = (message*)&buffer[8 + sizeof(message)];
}
return 0;
}
message::c is char[5]
so c[5]='\0' access outside of bound
c_str does contain the null terminate char, you can simply copy length()+1 given long enough buffer (not true in the code).
btw memset(msg.c, 0, 4) followed by memcpy(msg.c, str.c_str(), 4) doesn't make much sense, why you fill it if you're going to overwrite it immediately?

Trying to access object in an array of objects but only one object is saved

I'm trying to implement the GoBackN ARQ for a class. I'm attempting to read a file, break it up into packets of 30 characters and then store the packets in an array of packets. All of these packets are objects of the class packet.
Currently, this code compiles and runs however when I access the array of packets, at index 0 of the array I receive the last and most recent packet. When I attempt to access index 1, I expected a different packet, however, the packets are the same in all of the indices.
Why is the data in all of my packets the same?
int numPackets = 0;
packet *packetArray[30];
void addPacket(packet *p)
{
for (int i = 0; i < 30; i++)
{
if (packetArray[i])
{
continue;
}
else
{
packetArray[i] = p;
numPackets++;
break;
}
}
}
int main(int argumentCount, char *argumentVariables[]) {
char buffer[1024];
std::ifstream infile (argumentVariables[1], std::ifstream::binary);
infile.seekg (0, infile.end);
int lengthOfFile = infile.tellg();
infile.seekg (0, infile.beg);
int iterator = 0;
while(1)
{
if (lengthOfFile > 30)
{
bzero(buffer, 1024);
infile.read(buffer, 30);
lengthOfFile -= 30;
addPacket(new packet(1, iterator, strlen(buffer), buffer));
iterator++;
}
else
{
bzero(buffer, 1024);
infile.read(buffer, 30);
addPacket(new packet(1, iterator, strlen(buffer), buffer));
break;
}
}
packet * sendpckt = packetArray[0];
sendpckt->serialize(sendPayload);
printf("%s\n", sendPayload);
infile.close();
return 0;
}
Constructor code of the class packet.
packet::packet(int t, int s, int l, char * d){
type = t;
seqnum = s;
length = l;
data = d;
}
Can you show the constructor code of class "packet". First I think you must add a '\0' in the end of buffer after the "infile.read(buffer, 30)", second check if you are copying the buffer or only the address of the buffer to a "packet" member.

Receiving a Struct and Writing to file in socket programming

How to receive a struct over tcp socket and output to a file? I have a struct, which is a packet and I'm trying to send this over socket and receive it on the client side and write to the file. I'm using a void pointer as the buffer to store the file data
So far I have
struct packet {
int id;
void* data;};
I'm able to access the id, the int on the client side but when i write the data out to file. the file seems to be corrupted.
UPDATE:
The Server has a file open and will read from the file and make it into a packet and send the packet to the client.
Client will also have a file open for write, as it receives the packets it will write it out to the file.
Server Side:
current_packet = 0;
While(1)
{
struct packet *current = (packet *)malloc(packet_size+sizeof(int));
current->id = current_packet;
int read = fread(&current->data, 1, packet_size, file);
//end of file
if(read == 0){
break;
}
int byte_write = write(conn, current,read + sizeof(int));
current_packet++;
}
Client Side
current_packet = 0;
While(1)
{
struct packet *current = (packet *)malloc(packet_size+sizeof(int));
int read = read(conn, current, packet_size + sizeof(int));
//end of file
if(read == 0){
break;
}
int byte_write = fwrite(&current->data, 1, read - sizeof(int), file);
fflush(file);
}
struct packet *current = (packet *)malloc(packet_size+sizeof(int));
Supposed packet_size is something like
const size_t packet_size = 2048;
The code cited above might allocate something big enough to contain a packet, but the data pointer isn't initialized, and also not considered correctly in the allocation.
What I would do in your case:
Have a fixed size buffer allocated per packet like this:
struct packet {
const size_t packet_size = 2048;
int id;
std::array<unsigned char,packet_size> data;
};

Not able to print the char array as thought

#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);

Send other data types in winsock2

The send function in winsock2 accepts only char pointers.
How do I send integers or objects through it too?
const char *buf which you need to pass to send() function as an argument is just a pointer to array of bytes. You need to convert integers to bytes:
const int MAX_BUF_SIZE = 1024;
int int_data = 4;
const char *str_data = "test";
char *buf = (char*) malloc(MAX_BUF_SIZE);
char *p = buf;
memcpy(&int_data, p, sizeof(int_data));
p += sizeof(int_data);
strcpy(p, str_data);
p += strlen(str_data) + 1;
send(sock, buf, p - buf, 0);
free(buf);
and reading code:
const int MAX_BUF_SIZE = 1024;
int int_data = 0;
const char *str_data = NULL;
char *buf = (char*) malloc(MAX_BUF_SIZE);
char *p = buf;
recv(sock, buf, MAX_BUF_SIZE, 0);
memcpy(p, &int_data, sizeof(int_data));
p += sizeof(int_data);
str_data = malloc(strlen(p) + 1);
strcpy(str_data, p);
p += strlen(p) + 1;
free(buf);
and complex objects needs to be serialized to stream of bytes.
Note 1: The code sample is valid iff both server and client use the same platforms (x32 / x64 / ...) that means int has the same amount of bytes and byte order is the same.
Note 2: Writing code should check that there is no buffer (MAX_BUF_SIZE) overflow on each step.
Just store the value into a variable and then type-cast the variable to char*. The send() and recv() functions operate on binary data, despite taking char* parameters.
Sending:
int int_data = 4;
send(sock, (char*) &int_data, sizeof(int), 0);
Reading:
int int_data;
recv(sock, (char*) &int_data, sizeof(int), 0);
Generally, the easiest way is to print the integer or object to a string, and send that string. Textual representations are more portable, and also easier to debug.
std::stringstream may be a useful class both to create the string and parse it on the other end.