POSIX Message Queue, sending and receiving - c++

I have multiple threads that communicate using POSIX message queue.
double Pi_Msg(unsigned int p, unsigned int nn)
{
double *pis = new double[p];
struct mq_attr attr;
mqd_t mqdes;
char buf[256];
unsigned int prio;
attr.mq_maxmsg = p;
attr.mq_msgsize = 256;
attr.mq_flags = 0;
mqdes = mq_open("mq", O_RDWR|O_CREAT, 0664, &attr);
for (unsigned int i = 0; i < p; i++) {
int pid = fork();
if (pid < 0) {
exit(1);
} else if (pid != 0) {
wait();
mq_receive(mqdes, &buf[0], 256, NULL);
pis[i] = atoi(buf);
} else {
double pi = 3.1415;
char str[128];
sprintf(str, "%f", pi);
mq_send(mqdes, str, 128, 0);
exit(EXIT_SUCCESS);
}
}
}
ms_receive always returns -1 and I don't know why.

Related

icmp dereferencing pointer to incomplete type 'struct icmp'

I got an error:
dereferencing pointer to incomplete type 'struct ip'
138| u_int8_t icmp_Type = icmp_package->icmp_type;
I've made some research, found some similar topics on this, but nothing helped. The problem probably is with icmp.
The program works like traceroute in a Linux terminal.
None of these seem to work to fix it:
adding -D_GNU_SOURCE to gcc command
adding __USE_BSD
Does anyone know how to solve it?
Compiling on Linux with gcc -std=c17
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/time.h>
#include <unistd.h>
int receive_from(int sockfd, char recipient[20], int PID, int TTL, char response[20]);
void print_as_bytes (unsigned char* buff, ssize_t length)
{
for (ssize_t i = 0; i < length; i++, buff++)
printf ("%.2x ", *buff);
}
void print_row(int RCV_NUM, int avg, int TTL, char responses[3][20])
{
if(TTL < 10)
printf(" ");
printf("%d", TTL);
if(RCV_NUM == 0)
{
printf("*\n");
} else {
printf(" %s", responses[0]);
if(strcmp(responses[0], responses[1]) != 0)
printf(" %s", responses[1]);
if(strcmp(responses[0], responses[2]) != 0 && strcmp(responses[1], responses[2]) != 0)
printf(" %s", responses[2]);
if(RCV_NUM < 3)
printf(" ???\n");
else
printf(" %d ms", avg);
}
}
int receive(int sockfd, char recipient[20], int PID, int TTL)
{
int DEST_REACHED = 0;
char responses[3][20] = {"", "", ""};
struct timeval time;
gettimeofday(&time, NULL);
long long start = ((long long)time.tv_sec * 1000) + (time.tv_usec / 1000);
fd_set descriptors;
FD_ZERO(&descriptors);
FD_SET(sockfd, &descriptors);
struct timeval tv;
tv.tv_sec = 1;
tv.tv_usec = 0;
int time_passed = 0;
int which = 0;
while(which < 3)
{
int ready = select (sockfd+1, &descriptors, NULL, NULL, &tv);
if(ready < 0)
{
fprintf(stderr, "traceroute: select error: %s\n", strerror(errno));
which++;
}
if(ready > 0)
{
gettimeofday(&time, NULL);
long long timeNow = ((long long)time.tv_sec * 1000) + (time.tv_usec / 1000);
time_passed += timeNow - start;
int result = receive_from(sockfd, recipient, PID, TTL, responses[which]);
if(result == -1)
{
fprintf(stderr, "traceroute: Package missed\n");
which++;
continue;
}
if(result == 1)
{
DEST_REACHED = 1;
}
which++;
if(which == 3)
{ break; }
}
if(ready == 0)
{
which++;
}
}
int avg;
int RCV_NUM = 3;
if(which < 3)
{
RCV_NUM = which;
} else {
avg = time_passed / 3;
}
print_row(RCV_NUM, avg, TTL, responses);
return DEST_REACHED;
}
int receive_from(int sockfd, char recipient[20], int PID, int TTL, char response[20])
{
struct sockaddr_in sender;
socklen_t sender_len = sizeof(sender);
u_int8_t buffer[IP_MAXPACKET];
ssize_t packet_len = recvfrom (sockfd, buffer, IP_MAXPACKET, 0, (struct sockaddr*)&sender, &sender_len);
if (packet_len < 0) {
fprintf(stderr, "recvfrom error: %s\n", strerror(errno));
return EXIT_FAILURE;
}
char sender_ip_str[20];
inet_ntop(AF_INET, &(sender.sin_addr), sender_ip_str, sizeof(sender_ip_str));
printf ("Received IP packet with ICMP content from: %s\n", sender_ip_str);
struct ip* ip_header = (struct ip*) buffer;
ssize_t ip_header_len = 4 * ip_header->ip_hl;
struct icmp* icmp_package = (struct icmp*)((uint8_t *)ip_header + ip_header_len);
u_int8_t icmp_Type = icmp_package->icmp_type;
u_int8_t icmp_Code = icmp_package->icmp_code;
//We reached the destination point
if(icmp_Type == 0 && icmp_Code == 0)
{
if(icmp_package->icmp_hun.ih_idseq.icd_id == (u_int16_t) PID && icmp_package->icmp_hun.ih_idseq.icd_id == (u_int16_t) TTL)
{
inet_ntop(AF_INET, &(sender.sin_addr), response, 20);
return 1;
}
}
//Time Exceeded - we are not yet in the destination point
if(icmp_Type == 11 && icmp_Code == 0)
{
struct ip* ip_header_md = (struct ip *)((uint8_t *)icmp_package + 8);
struct icmp* icmp_package_md = (struct icmp *)((uint8_t *)ip_header_md + (*ip_header_md).ip_hl * 4);
if(icmp_package_md->icmp_hun.ih_idseq.icd_id == (u_int16_t) PID && icmp_package_md->icmp_hun.ih_idseq.icd_id == (u_int16_t) TTL)
{
inet_ntop(AF_INET, &(sender.sin_addr), response, 20);
return 0;
}
}
//Błąd
return -1;
}

server client sending receiving structure via raw data errors C++

I am doing a sending and receiving functions for structure(in my case "frame") via TCP/IP. But the functions don't seem to work out and I cannot find where my errors are. I am asked to store all the data in a char array and send it, while receiving the char array and convert them into the structure.
struct frame {
int length;
int * body;
int tail;
};
void winsock_client::send_frame(frame f) {
char * arr;
char * tx;
int length = 8 + f.length * sizeof(int);
arr = new char[length];
tx = (char*)&f.length;
for (int i = 0; i < sizeof(int); i++) {
arr[i] = *(tx++);
}
for (int i = 0; i < f.length; i++) {
tx =(char*)&f.body[i];
for (int j = 0; j < sizeof(int); j++) {
arr[4 + i * sizeof(int) + j] = *(tx++);
}
}
tx = (char*)&f.tail;
for (int i = 0; i < sizeof(int); i++) {
arr[4 + f.length * sizeof(int) + i] = *(tx++);
}
send(client_socket, arr, sizeof(arr), 0);
}
void winsock_server::receive_frame(frame & f) {
int * rx;
recv(server_socket, rx_buffer, sizeof(rx_buffer), 0);
rx =(int *) &rx_buffer[0];
f.length = *rx;
f.body = new int[f.length];
rx = (int *)&rx_buffer[4];
for (int i = 0; i < f.length; i++) {
f.body[i] = *(rx++);
}
rx = (int*)&rx_buffer[16];
f.tail = *rx;
}
Can anyone tell me what my errors are in my functions?
You are not checking the return values of send() and recv() to make sure that you are actually sending/receiving everything you are expecting. TCP is a streaming transport, there is no 1:1 relationship between sends and receives, like there is in UDP. Both functions can send/receive fewer bytes than requested, so you need to handle that.
Also, your read_frame() is using a fixed-length buffer to receive data, but you aren't taking into account how much data is actually being sent, so your buffer may not receive a full frame, or worse may receive a frame that is larger than it can hold.
The code is just plain ugly to read, too. It should be be re-written.
Try something more like this instead:
bool sendAll(SOCKET s, const void *buf, int len)
{
const char *pbuf = (const char*) buf;
while (len > 0)
{
int sent = send(s, pbuf, len, 0);
if (sent == SOCKET_ERROR)
return false;
pbuf += sent;
len -= sent;
}
return true;
}
bool winsock_client::send_frame(const frame &f)
{
int size = (2 + f.length) * sizeof(u_long);
char *arr = new char[size];
// multi-byte integers should always be transmitted in network
// byte order to avoid any endian issues across machine boundaries...
u_long *ptr = (u_long*) arr;
*ptr++ = htonl(f.length);
for (int i = 0; i < f.length; ++i)
*ptr++ = htonl(f.body[i]);
*ptr = htonl(f.tail);
bool result = sendAll(client_socket, arr, size);
delete[] arr;
return result;
}
bool recvAll(SOCKET s, void *buf, int len)
{
char *pbuf = (char*) buf;
while (len > 0)
{
int recvd = recv(s, pbuf, len, 0);
if (recvd <= 0) // -1 on error, 0 on disconnect
return false;
pbuf += recvd;
len -= recvd;
}
return true;
}
bool winsock_server::receive_frame(frame &f)
{
u_long temp;
if (!recvAll(server_socket, &temp, sizeof(temp)))
return false;
f.length = ntohl(temp);
u_long *arr = new u_long[f.length+1];
if (!recvAll(server_socket, arr, sizeof(u_long) * (f.length + 1)))
{
delete[] arr;
return false;
}
f.body = new int[f.length];
for(int i = 0; i < f.length; ++i)
f.body[i] = ntohl(arr[i]);
f.tail = ntohl(arr[f.length]);
delete[] arr;
return true;
}
Alternatively, you can simplify the code a bit if you take into account that the socket already does its own internal buffering for you:
bool sendAll(SOCKET s, const void *buf, int len)
{
const char *pbuf = (const char*) buf;
while (len > 0)
{
int sent = send(s, pbuf, len, 0);
if (sent == SOCKET_ERROR)
return false;
pbuf += sent;
len -= sent;
}
return true;
}
bool sendInt(SOCKET s, int value)
{
// multi-byte integers should always be transmitted in network
// byte order to avoid any endian issues across machine boundaries...
u_long temp = htonl(value);
return sendAll(s, &temp, sizeof(temp));
}
bool winsock_client::send_frame(const frame &f)
{
if (!sendInt(client_socket, f.length))
return false;
for (int i = 0; i < f.length; ++i)
{
if (!sendInt(client_socket, f.body[i]))
return false;
}
return sendInt(client_socket, f.tail);
}
bool recvAll(SOCKET s, void *buf, int len)
{
char *pbuf = (char*) buf;
while (len > 0)
{
int recvd = recv(s, pbuf, len, 0);
if (recvd <= 0) // -1 on error, 0 on disconnect
return false;
pbuf += recvd;
len -= recvd;
}
return true;
}
bool recvInt(SOCKET s, int &value)
{
u_long temp;
bool result = recvAll(s, &temp, sizeof(temp));
if (result) value = ntohl(temp);
return result;
}
bool winsock_server::receive_frame(frame &f)
{
if (!recvInt(server_socket, f.length))
return false;
f.body = new int[f.length];
for(int i = 0; i < f.length; ++i)
{
if (!recvInt(server_socket, f.body[i]))
{
delete[] f.body;
return false;
}
}
if (!recvInt(server_socket, f.tail))
{
delete[] f.body;
return false;
}
return true;
}

Stuck in a timeout loop from using alarm();

I'm attempting to implement a GoBackN protocol and when the server drops a packet, my alarm waits 2 seconds before sending all previously sent packets.
The alarm works and waits 2 seconds, however after the first timeout, the state machine I'm using gets stuck in a loop and continues to timeout. I think it might be because errno is not getting reset, but I'm not sure.
#define TIMEOUT_SECS 2
#define MAXTRIES 10
int base = 0;
int windowSize = 7;
int sendFlag = 1;
int tries = 0;
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;
}
}
}
void
CatchAlarm(int ignored) /* Handler for SIGALRM */
{
tries += 1;
errno = 0;
}
void
DieWithError()
{
printf("error");
exit (1);
}
int
max(int a, int b)
{
if (b > a)
return b;
return a;
}
int
min(int a, int b)
{
if(b>a)
return a;
return b;
}
typedef enum
{
wait,
sendData,
timeout,
receiveData
} e_state;
int main(int argumentCount, char *argumentVariables[])
{
//Grabbing all input information.
struct hostent *emulatorName;
emulatorName = gethostbyname(argumentVariables[1]);
int receiveFromEmulator = atoi(argumentVariables[3]);
int sendToEmulator = atoi(argumentVariables[2]);
//Setting up UDP socket for receiving from emulator.
int receiveSocket = 0;
receiveSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
//UDP socket configuration.
struct sockaddr_in receiveSocketStruct;
bzero((char *) &receiveSocketStruct, sizeof(receiveSocketStruct));
receiveSocketStruct.sin_family = AF_INET;
receiveSocketStruct.sin_port = htons(receiveFromEmulator);
receiveSocketStruct.sin_addr.s_addr = INADDR_ANY;
socklen_t receiveSocketLen = sizeof(receiveSocketStruct);
//Binding UDP socket so client can locate emulator.
bind(receiveSocket, (struct sockaddr *)&receiveSocketStruct, sizeof(receiveSocketStruct));
//Setting up UDP socket for sending to emulator.
int sendSocket = 0;
sendSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
//UDP socket configuration.
struct sockaddr_in sendSocketStruct;
bzero((char *) &sendSocketStruct, sizeof(sendSocketStruct));
sendSocketStruct.sin_family = AF_INET;
sendSocketStruct.sin_port = htons(sendToEmulator);
sendSocketStruct.sin_addr.s_addr = INADDR_ANY;
socklen_t sendSocketLen = sizeof(sendSocketStruct);
char buffer[1024];
std::ifstream infile (argumentVariables[4], std::ifstream::binary);
infile.seekg (0, infile.end);
int lengthOfFile = infile.tellg();
infile.seekg (0, infile.beg);
int totalPackets = 0;
int nextSeqNum = 0;
while(1)
{
if (lengthOfFile > 30)
{
bzero(buffer, 1024);
char * data = new char[1024];
infile.read(buffer, 30);
strncpy(data, buffer, 1024);
lengthOfFile -= 30;
if (nextSeqNum > 7)
{
nextSeqNum = 0;
}
addPacket(new packet(1, nextSeqNum, strlen(data), data));
totalPackets++;
nextSeqNum++;
}
else
{
bzero(buffer, 1024);
char * data = new char[1024];
infile.read(buffer, 30);
strncpy(data, buffer, 1024);
if (nextSeqNum > 7)
{
nextSeqNum = 0;
}
addPacket(new packet(1, nextSeqNum, strlen(data), data));
totalPackets++;
nextSeqNum++;
addPacket(new packet(3, nextSeqNum, 0, NULL));
totalPackets++;
break;
}
}
infile.close();
nextSeqNum = 0;
int packetsReceived;
int sentPackets;
int receive = 0;
char receivePayload[1024];
char sendPayload[1024];
struct sigaction myAction; /* For setting signal handler */
myAction.sa_handler = CatchAlarm;
if (sigfillset (&myAction.sa_mask) < 0) /* block everything in handler */
DieWithError ();
myAction.sa_flags = 0;
if (sigaction (SIGALRM, &myAction, 0) < 0)
DieWithError ();
e_state currentState = wait;
e_state previousState = wait;
while(1)
{
if (currentState == wait)
{
if (sendFlag == 1)
{
previousState = currentState;
currentState = sendData;
}
else
{
previousState = currentState;
currentState = receiveData;
}
}
else if (currentState == sendData)
{
if ((nextSeqNum < base + windowSize) && (nextSeqNum < totalPackets - 1))
{
//send packet with seqnum.
int sendPacket = 0;
bzero(sendPayload, 1024);
packet * sendpckt = packetArray[nextSeqNum];
sendpckt->serialize(sendPayload);
sendpckt->printContents();
sendPacket = sendto(sendSocket, sendPayload, sizeof(sendPayload), 0, (struct sockaddr *)&sendSocketStruct, sendSocketLen);
if (base == nextSeqNum)
{
alarm(0);
alarm(TIMEOUT_SECS);
}
nextSeqNum++;
}
else
{
sendFlag = 0;
previousState = currentState;
currentState = wait;
}
}
else if (currentState == timeout)
{
alarm(0);
alarm(TIMEOUT_SECS);
for(int counter = base; counter < nextSeqNum; counter++)
{
int sendPacket = 0;
bzero(sendPayload, 1024);
packet * sendpckt = packetArray[counter];
sendpckt->serialize(sendPayload);
sendpckt->printContents();
sendPacket = sendto(sendSocket, sendPayload, sizeof(sendPayload), 0, (struct sockaddr *)&sendSocketStruct, sendSocketLen);
}
sendFlag = 0;
previousState = currentState;
currentState = wait;
}
else if (currentState == receiveData)
{
bzero(receivePayload, 1024);
receive = (recvfrom(receiveSocket, receivePayload, sizeof(receivePayload), 0, (struct sockaddr *)&receiveSocketStruct, &receiveSocketLen));
if (errno == EINTR)
{
printf("timeout");
if (tries > MAXTRIES)
{
alarm(0);
break;
printf("recvfrom() failed.");
}
previousState = currentState;
currentState = timeout;
}
else
{
char buffer[1024];
bzero(buffer, 1024);
int receivePacketType;
int receivePacketSeqNum;
packet recvpckt(0, 0, 0, (char*)buffer);
recvpckt.deserialize((char*)receivePayload);
receivePacketSeqNum = recvpckt.getSeqNum();
receivePacketType = recvpckt.getType();
recvpckt.printContents();
if (receivePacketType == 2)
{
break;
}
base = receivePacketSeqNum + 1;
printf("%d\n", base);
if (base == nextSeqNum)
{
alarm(0);
}
else
{
alarm(0);
alarm(TIMEOUT_SECS);
}
if (nextSeqNum == totalPackets - 1)
{
nextSeqNum++;
int sendPacket = 0;
bzero(sendPayload, 1024);
packet * sendpckt = packetArray[nextSeqNum - 1];
sendpckt->serialize(sendPayload);
sendpckt->printContents();
sendPacket = sendto(sendSocket, sendPayload, sizeof(sendPayload), 0, (struct sockaddr *)&sendSocketStruct, sendSocketLen);
}
if (base <= totalPackets)
{
sendFlag = 1;
previousState = currentState;
currentState = wait;
}
else
{
continue;
}
}
}
else
{
break;
}
}
//Close shop.
close(receiveSocket);
close(sendSocket);
return 0;
}
The location where I suspect the loop to start is in the receiveData state.
Fixed it:
else if (currentState == receiveData)
{
receive = 0;
bzero(receivePayload, 1024);
receive = (recvfrom(receiveSocket, receivePayload, sizeof(receivePayload), 0, (struct sockaddr *)&receiveSocketStruct, &receiveSocketLen));
if (receive < 0)
{
printf("timeout");
if (tries > MAXTRIES)
{
alarm(0);
break;
printf("recvfrom() failed.");
}
previousState = currentState;
currentState = timeout;
}

Shared memory is working only the first time [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am using shared memory to pass values between processes. It's working the first time, but when I try changing it again, the value is not getting reflected in other processes. First process A changes the value and signal B. It uses it and passes back the control to A. Then A again changes the value, but this new value is not getting reflected in process B.
// FILE 1
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<arpa/inet.h>
#include<sys/time.h>
#include<iostream>
#include<netinet/in.h>
#include<sys/select.h>
#include<sys/shm.h>
#include<signal.h>
using namespace std;
struct shm
{
int aid;
int sid;
int bid;
int cid;
int portno;
int pno;
//int ports[4];
}*val;
int ports[4];
int sfds[4];
int count = 4;
void func1(int a)
{
fd_set rfds;
while (1)
{
FD_ZERO(&rfds);
struct timeval timer;
timer.tv_sec = 0;
timer.tv_usec = 10;
for (int i = 0; i < count; i++)
{
FD_SET(sfds[i], &rfds);
}
if (select(sfds[count - 1] + 1, &rfds, NULL, NULL, &timer))
{
for (int i = 0; i < count; i++)
{
if (FD_ISSET(sfds[i], &rfds))
{
val->pno = i;
val->portno = ports[i];
cout << "port number:" << val->portno << endl;
close(sfds[i]);
// Remove the corresponding sfd
for (int j = i; j < count - 1; j++)
{
sfds[j] = sfds[j + 1];
ports[j] = ports[j + 1];
}
count--;
kill(val->aid, SIGUSR2);
if (count > 0)
signal(SIGUSR1, &func1);
else
exit(1);
return;
}
}
}
}
}
void func2(int b)
{
struct sockaddr_in cliaddr;
socklen_t clilen;
int lc = 0;
for (int i = 0; i < 1; i++)
{
int nsfd = accept(sfds[val->pno], (struct sockaddr*) &cliaddr, &clilen);
if (nsfd < 0)
{
perror("Error");
exit(1);
}
cout << "Connection accepted";
send(nsfd, "OkaA", 5, 0);
close(nsfd);
}
if (close(sfds[val->pno]) < 0)
{
perror("Error closing");
exit(1);
}
cout << "Closed" << endl;
// Remove the corresponding sfd
for (int i = val->pno; i < count - 1; i++)
{
sfds[i] = sfds[i + 1];
ports[i] = ports[i + 1];
}
count--;
cout << " val->portnumber " << val->portno << endl;
kill(val->bid, SIGUSR1);
if (count > 0)
signal(SIGUSR2, &func2);
else
exit(1);
return;
}
int main()
{
int shmid = shmget(123456, sizeof(struct shm), IPC_CREAT | 0666);
if (shmid < 0)
{
perror("Error");
}
val = (struct shm*) shmat(shmid, NULL, 0);
//cout<<"yo2";
signal(SIGUSR1, &func1);
signal(SIGUSR2, &func2);
for (int i = 0; i < 4; i++)
{
//val->ports[i] = 7590+i;
sfds[i] = socket(AF_INET, SOCK_STREAM, 0);
const int optVal = 1;
const socklen_t optLen = sizeof(optVal);
int rtn = setsockopt(sfds[i], SOL_SOCKET, SO_REUSEADDR, (void*) &optVal,
optLen);
if (rtn < 0)
{
perror("Error");
exit(1);
}
struct sockaddr_in servaddr;
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(7590 + i);
ports[i] = i;
servaddr.sin_addr.s_addr = INADDR_ANY;
if (bind(sfds[i], (struct sockaddr*) &servaddr, sizeof(servaddr)) < 0)
{
perror("Error");
exit(1);
}
if (listen(sfds[i], 1) < 0)
{
perror("Error");
exit(1);
}
}
int c = fork();
if (c > 0)
{
val->aid = c;
val->sid = getpid();
kill(getpid(), SIGUSR1);
while (1)
;
}
else if (c == 0)
{
while (1)
;
}
else
{
perror("Error");
exit(1);
}
}
// FILE 2
#include<stdio.h>
#include<signal.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<arpa/inet.h>
#include<sys/time.h>
#include<iostream>
#include<netinet/in.h>
#include<sys/select.h>
#include<sys/shm.h>
using namespace std;
struct shm
{
int aid;
int sid;
int bid;
int cid;
int pno;
int portno;
}*val;
int sfds[4];
int count = 4;
void func1(int a)
{
int sfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in servaddr;
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(7590 + val->portno);
servaddr.sin_addr.s_addr = INADDR_ANY;
const int optVal = 1;
const socklen_t optLen = sizeof(optVal);
cout << val->portno << " vpn " << endl;
int rtn = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void*) &optVal,
optLen);
while (bind(sfd, (struct sockaddr*) &servaddr, sizeof(servaddr)) < 0)
{
perror("Error");
}
cout << endl << "Done" << endl;
if (listen(sfd, 1) < 0)
{
perror("Error");
exit(1);
}
for (int i = 0; i < 1; i++)
{
struct sockaddr_in cliaddr;
socklen_t clilen;
int nsfd = accept(sfd, (struct sockaddr*) &cliaddr, &clilen);
send(nsfd, "OkaB", 5, 0);
}
close(sfd);
signal(SIGUSR1, &func1);
kill(val->cid, SIGUSR1);
}
int main()
{
signal(SIGUSR1, &func1);
int shmid = shmget(123456, sizeof(struct shm), IPC_CREAT | 0666);
if (shmid < 0)
{
perror("Error");
}
val = (struct shm*) shmat(shmid, NULL, 0);
val->bid = getpid();
while (1)
;
}
The problem may come from the struct shm definition:
In file 1
struct shm
{
int aid;
int sid;
int bid;
int cid;
int portno;
int pno;
//int ports[4];
}*val;
In other file :
struct shm
{
int aid;
int sid;
int bid;
int cid;
int pno;
int portno;
}*val;
pno and portno are not at the same place.
And as LPs pointed, only one process should create the shared memory (IPC_CREAT)

how to correct convert char to byte in C++

I have some problem.
I write next code.
z=recv(conn,buff,512,0);//"Hi VahagnAAAAAAA" - but encrypted for example "zЖWЙЇ%ЂАЊ"S]яАAЧ0АбЯ.Щk5S¤Oц", length 32
BYTE messageLen = (BYTE)strlen(buff);// messageLen = 32
BYTE encryptedMessage[32];
memcpy(encryptedMessage, buff, messageLen);//!!!!!!!!!!!
DWORD encryptedMessageLen = messageLen;
CryptDecrypt(hSessionKeyRSA_2,NULL,TRUE,0,encryptedMessage, &encryptedMessageLen);
cout<<encryptedMessage<<endl;
I recv to buffer char array 32 length.
Where I copy encrypted text
"zЖWЙЇ%ЂАЊ"S]яАAЧ0АбЯ.Щk5S¤Oц"
to byte array, on the encryptedMessage have next value
"zЖWЙЇ%ЂАЊ"S]яАAЧ0АбЯ.Щk5S¤OцMMMMMMMMMMMMMMMMMMM"
where I decrypted I don't get start text, I get
"Ik VqagnеAAcS]‰МММММММММММ ММММММММ"
How I can fix it? please help me.
UPDATE
Client main()
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
const char* servername="127.0.0.1";
Sleep(2000);
setlocale(LC_ALL, "Russian");
WSADATA wsaData;
struct hostent *hp;
unsigned int addr;
struct sockaddr_in server;
int wsaret=WSAStartup(0x101,&wsaData);
if(wsaret)
return 0;
SOCKET conn;
conn=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(conn==INVALID_SOCKET)
return 0;
if(inet_addr(servername)==INADDR_NONE)
{
hp=gethostbyname(servername);
}
else
{
addr=inet_addr(servername);
hp=gethostbyaddr((char*)&addr,sizeof(addr),AF_INET);
}
if(hp==NULL)
{
closesocket(conn);
return 0;
}
server.sin_addr.s_addr=*((unsigned long*)hp->h_addr);
server.sin_family=AF_INET;
server.sin_port=htons(20248);
if(connect(conn,(struct sockaddr*)&server,sizeof(server)))
{
closesocket(conn);
return 0;
}
std::cout<<"Connected to server";
char buff[512];
memset(buff,'\0',512);
int z;
z=recv(conn,(char*)exportRSAKey,140,0);//Import RSA key
z=recv(conn,(char*)exportAESKey,140,0);//Import AES key
z=recv(conn,buff,512,0);//Get encryption text
importKey();//import key to client
BYTE messageLen = (BYTE)strlen(buff);
BYTE encryptedMessage[33];
memcpy(encryptedMessage, buff, messageLen);
DWORD encryptedMessageLen = messageLen;
CryptDecrypt(hSessionKeyRSA_2,NULL,FALSE,0,encryptedMessage, &encryptedMessageLen);
cout<<encryptedMessage<<endl;
// buff[z]=0;
}
Import key to client
if (CryptAcquireContext(&hCryptProv_RSA_2, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, 0))
{
printf("A cryptographic provider has been acquired.\r\n");
}
else
{
DWORD d = GetLastError();
return -1;
}
int iii = CryptImportKey(hCryptProv_RSA_2,(BYTE *)&exportAESKey,140,NULL,NULL,&hSessionKeyRSA_2);
if(CryptSetKeyParam(hSessionKeyRSA_2, KP_IV, exportRSAKey, 0))
{
cout<<"ok";
}
Server main()
std::cout<<"Client connected... "<<pParam<<std::endl;
char buff[512];
CString cmd;
CString params;
int n;
int x;
BOOL auth=false;
SOCKET client=(SOCKET)pParam;
strcpy(buff,"#Server Ready.\r\n");
char keybuff[1024];
createRSAPublicKey();//create enc_dec key
//keybuff = exportRSAKey;
//memset(rec,'\0',512);
const char *p = reinterpret_cast<const char*>(exportRSAKey);
send(client,p,140,0);//send RSA
const char *pp = reinterpret_cast<const char*>(exportAESKey);
send(client,pp,140,0);//Send AES
const char *ppp = reinterpret_cast<const char*>(encryptedMessage);
send(client,ppp,512,0);//Send encrypt text
createRSAPublicKey()
BOOL createRSAPublicKey()
{
if (CryptAcquireContext(&hCryptProv_AES, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, 0))
{
printf("A cryptographic provider has been acquired.\r\n");
}
else
{
DWORD d = GetLastError();
return -1;
}
HCRYPTKEY hSessionKey_AES;
if (!CryptGenKey(hCryptProv_AES, CALG_AES_256, CRYPT_EXPORTABLE, &hSessionKey_AES))
{
DWORD d = GetLastError();
return -1;
}
// Create RSA key to encrypt AES one
HCRYPTKEY hSessionKey;
if (!CryptGenKey(hCryptProv_AES, AT_KEYEXCHANGE, 1024 << 16, &hSessionKey))
{
DWORD d = GetLastError();
return -1;
}
// Export key
DWORD keylen;
BOOL ok = CryptExportKey(hSessionKey_AES, hSessionKey, SIMPLEBLOB, 0, exportRSAKey, &keylen);
if (ok == FALSE)
{
DWORD d = GetLastError();
return -1;
}
BYTE *encKey = (BYTE *)malloc(keylen);
ok = CryptExportKey(hSessionKey_AES, hSessionKey, SIMPLEBLOB, 0, exportAESKey, &keylen);
if (ok == FALSE)
{
DWORD d = GetLastError();
return -1;
}
else
printf("A cryptographic key export succeeded.\r\n");
BYTE messageLen = (BYTE)strlen(mess);
memcpy(encryptedMessage, mess, messageLen);
DWORD encryptedMessageLen = messageLen;
CryptEncrypt(hSessionKey_AES, NULL, TRUE, 0, encryptedMessage, &encryptedMessageLen, sizeof(encryptedMessage));
}
You are using strlen() to get the length of buff, but recv() does not null-terminate the buffer unless a null terminator was actually transmitted and read. You should instead be using the return value of recv(), which is the number of bytes actually read:
z=recv(conn,buff,512,0);
messageLen = z;//(BYTE)strlen(buff);
That being said, TCP is a byte stream, it has no concept of message boundaries. There is no 1-to-1 relationship between send() and recv() in TCP, like there is in UDP, so recv() above could read as little as 1 byte or as many as 512 bytes, and buff could contain a full message, a partial message, pieces of multiple messages, etc. You can't just blindly read and expect to receive everything in one go. You need to take all of that into account.
Design your TCP protocol to delimit messages, either with a preceding header that specifies the message length, or a trailing delimiter that never appears in the message body. Call recv() as many times as it takes, buffering any received data, and only process/decrypt complete messages that are in your buffer, leaving partial message data in the buffer to be completed by later reads.
Try something more like this:
Client main()
int readBuffer(SOCKET s, void *buffer, int buflen)
{
unsigned char *pbuf = (unsigned char*) buffer;
int total = 0;
while (total < buflen)
{
int num = recv(s, pbuf+total, buflen-total, 0);
if (num < 0)
return SOCKET_ERROR;
if (num == 0)
return 0;
total += num;
}
return total;
}
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
const char* servername="127.0.0.1";
setlocale(LC_ALL, "Russian");
WSADATA wsaData;
memset(&wsaData, 0, sizeof(wsaData));
int wsaret = WSAStartup(0x101, &wsaData);
if (wsaret != 0)
return 0;
struct sockaddr_in server;
memset(&server, 0, sizeof(server));
server.sin_addr.s_addr = inet_addr(servername);
if (server.sin_addr.s_addr == INADDR_NONE)
{
struct hostent *hp = gethostbyname(servername);
if (hp == NULL)
return 0;
server.sin_addr = *((in_addr*)hp->h_addr);
}
server.sin_family = AF_INET;
server.sin_port = htons(20248);
SOCKET conn = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (conn == INVALID_SOCKET)
return 0;
if (connect(conn, (struct sockaddr*)&server, sizeof(server)) != 0)
{
closesocket(conn);
return 0;
}
std::cout << "Connected to server";
if (readBuffer(conn, exportRSAKey, 140) <= 0) //Import RSA key
{
closesocket(conn);
return 0;
}
if (readBuffer(conn, exportAESKey, 140) <= 0) //Import AES key
{
closesocket(conn);
return 0;
}
importKey();//import key to client
DWORD messageLen;
if (readBuffer(conn, &messageLen, sizeof(messageLen)) <= 0) //Get encryption text length
{
closesocket(conn);
return 0;
}
messageLen = ntohl(messageLen);
std::vector<BYTE> buff(messageLen);
if (messageLen > 0)
{
if (readBuffer(conn, &buff[0], messageLen) <= 0) //Get encryption text
{
closesocket(conn);
return 0;
}
if (!CryptDecrypt(hSessionKeyRSA_2, NULL, FALSE, 0, &buff[0], &messageLen))
{
closesocket(conn);
return 0;
}
}
std::cout << std::string((char*)buff.data(), messageLen) << std::endl;
}
Server main()
int sendBuffer(SOCKET s, void *buffer, int buflen)
{
unsigned char *pbuf = (unsigned char*) buffer;
int total = 0;
while (total < buflen)
{
int num = send(s, pbuf+total, buflen-total, 0);
if (num < 0)
return SOCKET_ERROR;
if (num == 0)
return 0;
total += num;
}
return total;
}
...
SOCKET client = (SOCKET)pParam;
std::cout << "Client connected... " << pParam << std::endl;
...
createRSAPublicKey();//create enc_dec key
...
if (sendBuffer(client, exportRSAKey, 140) <= 0) //send RSA
{
closesocket(client);
return;
}
if (sendBuffer(client, exportAESKey, 140) <= 0) //Send AES
{
closesocket(client);
return;
}
...
DWORD tmpMessageLen = htonl(messageLen);
if (sendBuffer(client, &tmpMessageLen, sizeof(tmpMessageLen)); //Send encrypt text length
{
closesocket(client);
return;
}
if (sendBuffer(client, encryptedMessage, messageLen) <= 0) //Send encrypt text
{
closesocket(client);
return;
}
...