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

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

问题描述

我正在尝试在 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: 
" << q1.getQuestion()<<endl;
    cout << q1.getOpt1() << endl << q1.getOpt2() << endl << q1.getOpt3() << endl << q1.getCorrect()<<endl;

    cout << "

 --- Server starting up --- 

";

    /*
     * 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
", 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 << "
 Usage: %s <ip of server> 
",argv[0];
        return 1;
    }

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

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

    if(inet_pton(AF_INET, argv[1], &servAddr.sin_addr)==-1){
        cerr << "
 Unable to convert given IP to Network Form 
 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
";
    }
    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: 
" << 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天全站免登陆