将对象通过服务器传递到客户端 [英] Passing Object over Server to client

查看:129
本文介绍了将对象通过服务器传递到客户端的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在linux中创建一个客户端服务器应用程序。服务器应该向所有连接的客户端发送一个对象。
下面是它的代码。
在此当服务器发送对象时,一切在服务器端保持确定,但在客户端服务器收到分段故障时立即收到它。

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.

伺服器:

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

问题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_ */


推荐答案

你需要序列化你的对象。这通常涉及到使它成为一个字符串,可以在任何东西通过发送对象的另一个边阅读。

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.

这是完全相同的问题,如果你是写数据到一个文件,你不想存储OBJECT,你想存储有效载荷或内容是在类内。

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.

您可以使用 stringstream 形成一个长字符串的数据,并传递由此形成的字符串。

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

类似:

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...

这篇关于将对象通过服务器传递到客户端的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆