【问题标题】:Send data over TCP to JSON Server from C++ Client从 C++ 客户端通过 TCP 向 JSON 服务器发送数据
【发布时间】:2019-01-01 08:17:57
【问题描述】:

我正在尝试使用 JSON 从 C++ 中的客户端通过 TCP 将数据发送到本地服务器。这是我的 JSON 服务器

comm.js

'use strict';

const net = require('net');


var client = new net.Socket();
var _SIGNATURE = 206;

client.connect(5000, '192.168.1.107', function () {
  let info = {
    "alo":"alo"
  }

  let message = JSON.stringify(info);


    var messageLength = Buffer.byteLength(message, 'utf8');
    var buffer = Buffer.alloc(messageLength + 6);
  console.log(buffer);

    buffer.writeUInt16LE(_SIGNATURE, 0);
  console.log(buffer);

    buffer.writeUInt32LE(messageLength, 2);
  console.log(buffer);

    buffer.write(message, 6);
  console.log(buffer);
  console.log(`${buffer} -> ${messageLength}` );

  client.write(buffer);

})

还有我的 C++ 客户端

/**
    C++ client
*/
#include<iostream>    //cout
#include <sstream>
#include<stdio.h> //printf
#include<string.h>    //strlen
#include<string>  //string
#include<sys/socket.h>    //socket
#include<arpa/inet.h> //inet_addr
#include<netdb.h> //hostent

using namespace std;

/**
    TCP Client class
*/
class tcp_client  {

private:

    int sock;
    std::string address;
    int port;
    struct sockaddr_in server;

public:

    tcp_client();
    bool conn(string, int);
    bool send_data(string data);
    string receive(int);
};

tcp_client::tcp_client()  {
    sock = -1;
    port = 0;
    address = "";
}

/**
    Connect to a host on a certain port number
*/
bool tcp_client::conn(string address , int port)  {
    //create socket if it is not already created
    if(sock == -1)
    {
        //Create socket
        sock = socket(AF_INET , SOCK_STREAM , 0);
        if (sock == -1)
        {
            perror("Could not create socket");
        }

        cout<<"Socket created\n";
    }
    else    {   /* OK , nothing */  }

    //setup address structure
    if(inet_addr(address.c_str()) == -1)  {

        struct hostent *he;
        struct in_addr **addr_list;

        //resolve the hostname, its not an ip address
        if ( (he = gethostbyname( address.c_str() ) ) == NULL)  {

            //gethostbyname failed
            herror("gethostbyname");
            cout<<"Failed to resolve hostname\n";

            return false;
        }

        //Cast the h_addr_list to in_addr , since h_addr_list also has the ip address in long format only
        addr_list = (struct in_addr **) he->h_addr_list;

        for(int i = 0; addr_list[i] != NULL; i++) {
            //strcpy(ip , inet_ntoa(*addr_list[i]) );
            server.sin_addr = *addr_list[i];

            cout<<address<<" resolved to "<<inet_ntoa(*addr_list[i])<<endl;

            break;
        }
    }

    //plain ip address
    else  {
        server.sin_addr.s_addr = inet_addr( address.c_str() );
    }

    server.sin_family = AF_INET;
    server.sin_port = htons( port );

    //Connect to remote server
    if (connect(sock , (struct sockaddr *)&server , sizeof(server)) < 0)  {

        perror("connect failed. Error");
        return 1;
    }

    cout<<"Connected\n";
    return true;
}

/**
    Send data to the connected host
*/
bool tcp_client::send_data(string data) {

    //Send some data
    if( send(sock , data.c_str() , strlen( data.c_str() ) , 0) < 0) {

        perror("Send failed : ");
        return false;
    }
    cout<<"Data send\n";

    return true;
}

/**
    Receive data from the connected host
*/
string tcp_client::receive(int size=512)  {

    char buffer[size];
    string reply;

    //Receive a reply from the server
    if( recv(sock , buffer , sizeof(buffer) , 0) < 0) {

        puts("recv failed");
    }

    reply = buffer;
    return reply;
}

int main(int argc , char *argv[]) {

    tcp_client c;
    string host, test;

    host = "192.168.1.107";

    cout<<"Hostname : 192.168.1.107:5000";

    //connect to host
    c.conn(host , 5000);

    //send some data
    std::cout << "Enter string to send:" << '\n';
    cin >> test;


    c.send_data(test);

    //receive and echo reply
    cout<<"----------------------------\n\n";
    cout<<c.receive(1024);
    cout<<"\n\n----------------------------\n\n";

    //done
    return 0;
}

问题是 JSON 服务器需要首先接收字节形式的 _SIGNATURE 206 的值才能识别数据,否则它会崩溃。我尝试过位移,但没有奏效,我还在客户端的数据字符串上尝试了memset(),尽管这也失败了。 我正在研究以找到解决方案,但希望这里有人知道答案,也许与发送函数中的数据缓冲区有关? 任何帮助表示赞赏!

【问题讨论】:

  • 我还应该指出,TCP 服务器和客户端是分开工作的,这意味着如果我使用使用普通 TCP 参数的服务器连接客户端,如果我使用 JSON 客户端,那么服务器也可以工作。
  • char buffer[size]; 不是有效的 C++,它是 VLA
  • JSON server needs to receive 我在服务器代码中没有看到这个。我看到服务器 正在写入 _SIGNATURE 流向客户端。
  • 为什么不使用标准协议(如HTTP)来控制通信通道?
  • 一旦你解决了错误(不是之前)。您应该将此代码发送至codereview.stackexchange.com

标签: c++ json node.js tcp


【解决方案1】:

您在使用send/recv 时犯了一些常见错误:

  • send 不一定发送整个缓冲区。您需要继续调用send,直到发送完所有字节。
  • recv 可能接收到的数据少于预期,并且接收到的数据不是以零结尾的,因此您不能对其执行strlen 或将其传递给std::string。而是使用reply.append(buffer, received_bytes);,其中received_bytes 是recv 的返回值。

【讨论】:

    猜你喜欢
    • 2015-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-27
    • 2013-12-26
    • 2014-03-08
    • 2021-02-21
    • 1970-01-01
    相关资源
    最近更新 更多