Passing Object over Server to client

邮差的信 提交于 2019-12-08 10:28:45

问题


I am trying to create a client server application in linux. Server is supposed to send one object to all connected clients. Here is the code for it. In this When server send object, everything remains ok at server side but Segmentation fault occurs on client server immediately it receive it.

Server:

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

Client:

#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_ */

回答1:


You will need to "serialize" your object. This usually involves making it into a string that can be read at the other "side" of whatever thing you are sending the object through.

It is exactly the same issue as if you were to write the data to a file, you don't want to store the OBJECT, you want to store the "payload" or "content" of that is inside the class.

You can use stringstream to form a long string of your data, and pass the string formed from that.

Something like:

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

You will obviously need to parse the resulting string at the other end - and , may not be the ideal separator. Feel free to use something else...



来源:https://stackoverflow.com/questions/15391582/passing-object-over-server-to-client

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!