Передача объекта через сервер клиенту

Я пытаюсь создать клиент-серверное приложение в Linux. Сервер должен отправлять один объект всем подключенным клиентам.
Вот код для этого.
В этом случае, когда сервер отправляет объект, все остается в порядке на стороне сервера, но на клиентском сервере происходит ошибка сегментации сразу же после его получения.

Сервер:

#include "Question.h"#include <iostream>
#include <string.h>
using namespace std;

#include<sys/socket.h>
#include<sys/types.h>
#include<stdio.h>
#include<arpa/inet.h>
#include<time.h>

#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <netinet/in.h>

int main() {
Question q1("Capital Of Pakistan?", "Lahore", "Karachi", "Quetaa", "Islamabad");

int socketID = 0, clientID[10] = {0}, totalClients = 3;
char sendBuffer[1024];
memset(sendBuffer, '0', sizeof(sendBuffer));

time_t time;
struct sockaddr_in servAddr;

cout << "Question is: \n" << q1.getQuestion()<<endl;
cout << q1.getOpt1() << endl << q1.getOpt2() << endl << q1.getOpt3() << endl << q1.getCorrect()<<endl;

cout << "\n\n --- Server starting up --- \n\n";

/*
* Creating Socket
*/
socketID = socket(AF_INET, SOCK_STREAM, 0);
if (socketID == -1) {
cerr << " Can't create Socket";
}

servAddr.sin_family = AF_INET;
servAddr.sin_port = htons(5000);
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);

/*
* Binding IP
*/
int bindID;
bindID = bind(socketID, (struct sockaddr *) &servAddr, sizeof(servAddr)); // Casting sockaddr_in on sockaddr and binding it with socket id
if (bindID != -1) {
cout << " Bind SucessFull";

listen(socketID, 5);
cout << " Server Waiting for connections" << endl;
int i = 0;
while (1) {
clientID[i] = accept(socketID, (struct sockaddr *) NULL, NULL);
cout << "Got Client: " << i+1 << ","<<totalClients-(i+1)<<" to go" << endl;
cout << "ID: " << clientID[i]<<endl;
cout.flush();
snprintf(sendBuffer, sizeof(sendBuffer), "%.24s\n", ctime(&time));
write(clientID[i], sendBuffer, strlen(sendBuffer));

i++;
if (i >= totalClients)
break;
sleep(1);
}
cout << "Sending Question to All Clients...." << endl;
for(int j=0; j<totalClients; j++) {
cout << "Sending to ID " << clientID[j]<<endl;
write(clientID[j], &q1 , sizeof(q1));
cout << "Sent " << j << "...." << endl;
}
/*
* Closing all clients
*/
for (int k = 0; k < totalClients; k++) {
close(clientID[k]);
}
} else {
cerr << " Unable to Bind";
}
return 0;
}

Клиент:

#include "Question.h"#include <iostream>
#include <string.h>
using namespace std;

#include<sys/socket.h>
#include<sys/types.h>
#include<stdio.h>
#include<arpa/inet.h>
#include<time.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>int main(int argc, char *argv[])
{
int socketID = 0 /*Socket Descriptor*/, n = 0;
char recvBuffer[1024];

memset(recvBuffer, '0',sizeof(recvBuffer));

struct sockaddr_in servAddr;

if(argc!=2){
cout << "\n Usage: %s <ip of server> \n",argv[0];
return 1;
}

socketID = socket(AF_INET, SOCK_STREAM, 0);
if(socketID == -1){
cerr << "\n Can't create socket \n";
return 1;
}

servAddr.sin_family = AF_INET;
servAddr.sin_port = htons(5000);

if(inet_pton(AF_INET, argv[1], &servAddr.sin_addr)==-1){
cerr << "\n Unable to convert given IP to Network Form \n inet_pton Error";
return 1;
}

int connectFlag;
connectFlag = connect(socketID, (struct sockaddr *)&servAddr, sizeof(servAddr));
if(connectFlag == -1){
cout << " Connection Failed" << endl;
return 1;
}
n = read(socketID, recvBuffer, sizeof(recvBuffer)-1);
recvBuffer[n] = 0;
cout << recvBuffer << endl;

if(n < 0){
cerr << "Buffer Read error\n";
}
Question q1;
cout << "Gonna Receive Connections"<<endl;
q1.setAll("0","0","0","0","0");
cout.flush();
n = read(socketID, &q1, sizeof(q1));
cout << n << endl;
cout << "Received Question " << endl;
cout << "Question is: \n" << q1.getQuestion()<<endl;
cout << q1.getOpt1() << endl << q1.getOpt2() << endl << q1.getOpt3() << endl << q1.getCorrect()<<endl;
cout.flush();

return 0;
}

Question.h

#ifndef QUESTION_H_
#define QUESTION_H_

#include <iostream>
using namespace std;

class Question {
private:
string question;
string opt1;
string opt2;
string opt3;
string correct;
public:
/*
* Constructors
*/
Question();
Question(string, string, string, string, string);

void setAll(string, string, string, string, string);
string getCorrect() const;
void setCorrect(string correct);
string getOpt1() const;
void setOpt1(string opt1);
string getOpt2() const;
void setOpt2(string opt2);
string getOpt3() const;
void setOpt3(string opt3);
void setQuestion(string question);
string getQuestion() const;

};

#endif /* QUESTION_H_ */

0

Решение

Вам нужно будет «сериализовать» ваш объект. Обычно это включает в себя превращение его в строку, которая может быть прочитана на другой «стороне» любой вещи, через которую вы отправляете объект.

Это точно такая же проблема, как если бы вы записывали данные в файл, вы не хотите хранить ОБЪЕКТ, вы хотите хранить «полезную нагрузку» или «содержимое» внутри класса.

Ты можешь использовать stringstream чтобы сформировать длинную строку ваших данных, и передать строку, сформированную из этого.

Что-то вроде:

class A
{
int x;
string s;
};

...
class A a;

stringstream ss;

ss << a.x << ", " << a.s << endl;

....
write(clientID[j], ss.str.c_str(), ss.str.length());

Вам, очевидно, нужно будет проанализировать полученную строку на другом конце — и , не может быть идеальным разделителем. Не стесняйтесь использовать что-то еще …

2

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector