【问题标题】:Receiving strings in C++ from Python从 Python 接收 C++ 中的字符串
【发布时间】:2019-03-17 13:01:50
【问题描述】:

我正在尝试通过套接字从客户端(Python)向服务器(C++)发送布尔值。

所以我使用了 json 并将布尔值转换为字符串格式并通过套接字发送字符串。

这是我的代码: 客户端(Python):

# TCP Client Code

host="128.0.0.1"            # Set the server address to variable host

port=8080               # Sets the variable port to 4446

from socket import *             # Imports socket module
import json

s=socket(AF_INET, SOCK_STREAM)      # Creates a socket



s.connect((host,port))          # Connect to server address
print "Successfully connected to the server and ready to send some data"

data= json.dumps("{\"A\":true,\"B\":false,\"C\":false,\"D\":false}")

s.send(data)



msg=s.recv(1024)            # Receives data upto 1024 bytes and stores in variables msg

print "Message from server : " + msg

s.close()                            # Closes the socket
# End of code

现在我以字符串格式和 \n \t 标签一起接收它们。 如何解释发送的布尔值并将它们分配给 C++ 中所需的变量。

这是我在服务器端 (C++) 的代码:

using namespace std;
//Server side
int main(int argc, char *argv[8080])
{
bool Style1;
    //buffer to send and receive messages with
    char msg[1500];

    //setup a socket and connection tools
    sockaddr_in servAddr;
    memset((char*)&servAddr, 0,sizeof(servAddr));
    servAddr.sin_family = AF_INET;
    servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servAddr.sin_port = htons(8080);

    //open stream oriented socket with internet address
    //also keep track of the socket descriptor
    int serverSd = socket(AF_INET, SOCK_STREAM, 0);
    if(serverSd < 0)
    {
        cerr << "Error establishing the server socket" << endl;
        exit(0);
    }


    //bind the socket to its local address
    int bindStatus = bind(serverSd, (struct sockaddr*) &servAddr, 
        sizeof(servAddr));
    if(bindStatus < 0)
    {
        cerr << "Error binding socket to local address" << endl;
        exit(0);
    }
    cout << "Waiting for a client to connect..." << endl;


    //listen for up to 5 requests at a time
    listen(serverSd, 5);


    //receive a request from client using accept
    //we need a new address to connect with the client
    sockaddr_in newSockAddr;
    socklen_t newSockAddrSize = sizeof(newSockAddr);


    //accept, create a new socket descriptor to 
    //handle the new connection with client
    int newSd = accept(serverSd, (sockaddr *)&newSockAddr, &newSockAddrSize);
    if(newSd < 0)
    {
        cerr << "Error accepting request from client!" << endl;
        exit(1);
    }
    cout << "Connected with client!" << endl;


        //receive a message from the client (listen)
        cout << "Awaiting client response..." << endl;
        memset(&msg, 0, sizeof(msg));//clear the buffer

        recv(newSd, (char*)&msg, sizeof(msg), 0);
        if(!strcmp(msg, "exit"))
        {
            cout << "Client has quit the session" << endl;

        }
        string str(msg);
        cout << "Client: " << msg << endl;
        cout << ">";
        string data = "Instructions Received \n";
        memset(&msg, 0, sizeof(msg)); //clear the buffer
        strcpy(msg, data.c_str());
        if(data == "exit")
        {
            //send to the client that server has closed the connection
            send(newSd, (char*)&msg, strlen(msg), 0);

        }
        //send the message to client
        send(newSd, (char*)&msg, strlen(msg), 0);

    //we need to close the socket descriptors after we're all done



    close(newSd);
    close(serverSd);

    cout << "Connection closed..." << endl;
    return 0;   
}

我是初学者,感谢各位帮助我。

仅供参考 - 如果我在收到字符串后在 C++ 中打印它看起来像这样

"{\"A\":true,\"B\":false,\"C\":false,\"D\":false}"

感谢大家的建议,我尝试在 C++ 中使用 json 并进行了一些更改

#include<iostream>
#include <jsoncpp/json/json.h>
using namespace std;

    void decode()
    {
         bool a,b,c,d;
        string text = "{\"A\":true,\"B\":false,\"C\":false,\"D\":false}";
            Json::Value root;
            Json::Reader reader;
            bool parsingSuccessful = reader.parse( text, root );
            if ( !parsingSuccessful )
                    {
                        cout << "Error parsing the string" << endl;
                    }


            const Json::Value mynamesA = root["A"];
            const Json::Value mynamesB = root["B"];
            const Json::Value mynamesC = root["C"];
            const Json::Value mynamesD= root["D"];


            cout<<mynamesA<<endl;
            cout<<mynamesB<<endl;
            cout<<mynamesC<<endl;
            cout<<mynamesD<<endl;


    }

    int main()
    {   
    decode();
        return 0;
    }

现在开始打印了

true
false
false
false

正如预期的那样。 但我想将这些值分配给bool a,b,c,d; 我该怎么做??

【问题讨论】:

标签: python c++ json sockets deserialization


【解决方案1】:

如果可能,最好使用 JSON 解析库。这是您可以使用的 RapidJSON 教程的link

如果您想自己编写解决方案,请尝试以下方法。

自编码解决方案

遍历字符串找到"\"" 的所有索引并将它们存储在一个向量中。如果您的键值对中的值都不是字符串,那么您可以使用它来查找键。所以,如果你有一个包含 3 和 7 的向量,那么你的密钥从 4 开始到 6 结束。

您可以使用类似的逻辑来提取值。遍历字符串并找到第一次出现的“:”。在此之后,找到第一次出现的“,”,它位于最后一次找到的“:”的索引之后。所以,如果你有 9 和 15,那么你的值将从 11 开始,到 14 结束。

请注意,根据您的示例,当您达到最后一个值时,它将以“]”结尾。因此,如果找不到逗号,则查找“]”或可能的“”。

bool findKeyIndices(string s, vector<int> & kIndices) {
    string substr = "\"";
    vector<int> indices;

    size_t index = s.find(substr, 0);

    while (index != string::npos) {
         indices.push_back(index);
         s.find(substr, index+1);
    }

    if (indices.size() % 2 != 0)
          return FALSE;

    for(int x =0; x < indices.size(); x++) {
         if(indices.at(x) % 2 == 0) {
               kIndex.push_back(++x);
         } else {
               kIndex.push_back(--x)
         }
    }

    return TRUE;
} 

bool findValIndices(string s, vector<int> & vIndices){
  string start = ": ", endOne = ",", endTwo = "]";
  vector<int> indices;

  size_t index = s.find(start, 0), backupIndex;

  while (index != string::npos) {
         indices.push_back(index);

         backupIndex = index;

         s.find(endOne, index+1);
         if(index != string::npos) {
              indices.push_back(index);
         } else {
              s.find(endTwo, backupIndex + 1);
              if(backupIndex != string::npos){
                    index = backupIndex;
              } else {
                    return FALSE;
              }

         }
    }

    if (indices.size() % 2 != 0)
           return FALSE;

    for(int x =0; x < indices.size(); x++) {
         if(indices.at(x) % 2 == 0) {
               vIndex.push_back(x + 2);
         } else {
               vIndex.push_back(--x)
         }
    }

 }

如果您可以假设值只会是真或假,那么解决方案可能会更简单。在这种情况下,您可以找到每个键的起始索引以及所有“true”和“false”子字符串的起始索引。然后你可以从那里找出哪个键与真或假相关联。

例如,如果键的 起始 索引有 [2, 10] 并且“true”的起始索引是 4,那么从 2 开始的键将与true 因为 key1-start

增强算法

上述算法假设您的键值对中的值都不是字符串。您可以修改上面的代码,这样您就不必做出这样的假设。

步骤如下:

  1. 查找所有出现的“\”并将索引存储在向量中 (称之为quoteIndices)
  2. 查找所有出现的逗号并存储 向量中的索引
  3. 找到可以被字符的索引 用于查找最后一个值的结尾。在你的例子中 cmets,它是“]”。

使用以下等式确定键值对:

quote-open-indx

现在,x 可以是一个值或一个字符串。使用类似下面的过程来确定 x 是什么并进行相应的解析。

  1. quoteIndices 中的第一个和第二个索引将始终包含一个键。因此,您可以假设第一个 quote-end-index 位于 quoteIndices.at(1)。假设它等于 5。
  2. 如果 quoteIndices 中有另一个值更大 大于 5 但小于第一个逗号索引,那么您的值是 细绳。否则,它不是。

【讨论】:

  • 仅供参考 - 如果我在服务器端 (C++) "\n{\n\t[\"A\":true,\"B\":false,\"C\":false,\"D\":false]\n}" 打印字符串,这就是字符串的样子
  • 好的,明白了。稍微调整了我的答案。希望这会有所帮助。
  • 这是非常复杂、脆弱且容易出错的。为什么不使用现有的 JSON 库?
  • @Graindor root["A"].get&lt;bool&gt;() (等)应该可以解决问题。您还可以使用隐式转换:bool a = root["A"]; 有效。
  • @Graindor 我通读了 Json::Value 类的文档,我相信你应该能够做到以下几点:if (root["A"] == TRUE) a = TRUE; ELSE IF (root["A"] == FALSE) a = FALSE; ELSE cout &lt;&lt; "error" &lt;&lt; endl;
【解决方案2】:

最好控制实际发送的内容。

这一行:

data= json.dumps("{\"A\":true,\"B\":false,\"C\":false,\"D\":false}")

高度怀疑:当应该在对象上使用 json.dumps 来生成 json 字符串时,你在已经是 json 编码的字符串上使用它。

我在交互式 Python 中对其进行了测试并得到:

>>> data= json.dumps("{\"A\":true,\"B\":false,\"C\":false,\"D\":false}")
>>> print(data)
"{\"A\":true,\"B\":false,\"C\":false,\"D\":false}"
>>> print([(i, hex(ord(i))) for i in data])   # control individual characters
[('"', '0x22'), ('{', '0x7b'), ('\\', '0x5c'), ('"', '0x22'), ('A', '0x41'), ('\\', '0x5c'), ('"', '0x22'), (':', '0x3a'), ('t', '0x74'), ('r', '0x72'), ('u', '0x75'), ('e', '0x65'), (',', '0x2c'), ('\\', '0x5c'), ('"', '0x22'), ('B', '0x42'), ('\\', '0x5c'), ('"', '0x22'), (':', '0x3a'), ('f', '0x66'), ('a', '0x61'), ('l', '0x6c'), ('s', '0x73'), ('e', '0x65'), (',', '0x2c'), ('\\', '0x5c'), ('"', '0x22'), ('C', '0x43'), ('\\', '0x5c'), ('"', '0x22'), (':', '0x3a'), ('f', '0x66'), ('a', '0x61'), ('l', '0x6c'), ('s', '0x73'), ('e', '0x65'), (',', '0x2c'), ('\\', '0x5c'), ('"', '0x22'), ('D', '0x44'), ('\\', '0x5c'), ('"', '0x22'), (':', '0x3a'), ('f', '0x66'), ('a', '0x61'), ('l', '0x6c'), ('s', '0x73'), ('e', '0x65'), ('}', '0x7d'), ('"', '0x22')]

这证明有问题的双引号 (") 和反斜杠 (\) 已由 Python 代码发送。

你想要的可能是:

data = '{"A":true,"B":false,"C":false,"D":false}'  # directly store the json string

# build the json string from a dict
data = json.dumps({'A': True, 'B': False, 'C': False, 'D': False})

【讨论】:

    猜你喜欢
    • 2017-10-25
    • 1970-01-01
    • 1970-01-01
    • 2021-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-05
    • 2013-07-08
    相关资源
    最近更新 更多