strtok() 更改我的缓冲区,我需要存储一些在任意时间更改的数据,我该怎么做?

Posted

技术标签:

【中文标题】strtok() 更改我的缓冲区,我需要存储一些在任意时间更改的数据,我该怎么做?【英文标题】:strtok() change my buffer, I need stored some data that change in an arbitrary time, how can I do this? 【发布时间】:2021-08-20 04:46:56 【问题描述】:

我有一个坐标列表,其中包含从 Python 服务器发送到 C++ 客户端(如缓冲区)的坐标,然后我需要拆分每个坐标,为此我使用了 strtok(),但是当第一次对函数进行标记时,请执行此操作正确地,当我的 while 循环重复并收到一个新的坐标列表时,该函数返回先前拆分的第一个标记,我需要保存新的坐标列表并将其拆分为标记,就像第一次一样,任何人都知道我的问题是什么或更好不使用 strtok() 的解决方法?

这是我的 C++ 客户端代码

#define _CTR_SECURE_NO_WARNINGS
#include <stdio.h>  
#include <Winsock2.h>  
#pragma comment(lib,"ws2_32.lib")
#pragma warning(disable:4996)
#include <iostream>
#include <sstream>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
#include <typeinfo>

using namespace std;

int main()

    char delimitador[] = ",";
    WORD wVersionRequested;
    WSADATA wsaData;
    int err, N;
    char* length;
    string D, Coordenada;

    wVersionRequested = MAKEWORD(1, 1);

    err = WSAStartup(wVersionRequested, &wsaData);
    if (err != 0) 
        return -1;
    

    if (LOBYTE(wsaData.wVersion) != 1 ||
        HIBYTE(wsaData.wVersion) != 1) 
        WSACleanup();
        return -1;
    
    SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0);

    SOCKADDR_IN addrSrv;
    addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    addrSrv.sin_family = AF_INET;
    addrSrv.sin_port = htons(2070);
    connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));

    const char* baseCh =  "hello" ;
    char recvBuf[50], expected[50];

    send(sockClient, baseCh, strlen(baseCh), 0);

        while (1 == 1)
        

            recv(sockClient, recvBuf, strlen(recvBuf), 0);

            strcpy(expected, recvBuf);  

            char *token = strtok(expected, delimitador);
            if (token != NULL); 
                while (token != NULL) 
                    printf("Token %s\n", token);
                    token = strtok(NULL, delimitador);
                
            

            send(sockClient, baseCh, strlen(baseCh), 0);

        

    closesocket(sockClient);
    WSACleanup();

    getchar();
    return 0;


这是我的 Python 服务器代码

import socket
import time

def main():
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.bind(("localhost", 2070))
    server.listen(0)
    connection, address = server.accept()
    Hand = []
    while True:

        recv_str=connection.recv(1024)[0:5]
        print("enter 1")
        recv_str=recv_str.decode("ascii")
        if not recv_str:
            break
        print( recv_str)
        
        while True:
            time.sleep(0.5)
            Hand.append(1)
            Hand.append(20)
            Hand.append(25)
            connection.send( bytes("%s," %Hand, encoding="ascii"))
            recv_str=connection.recv(1024)[0:5]
            print(Hand)
            print(recv_str)
            Hand = []
            
    connection.close()
    input("enter end")

if __name__ == '__main__':
   main()

enter image description here

我已经放了我使用的正确代码,主要问题是我需要在未定义的时间连续接收来自 Python 服务器的消息,这个消息是一组坐标,你如何看到函数 strtok () 更改我的缓冲区,我只需要拆分数据而不更改原始缓冲区变量,就像我的第一个标记化结果一样,但每次我的缓冲区更改时。

【问题讨论】:

strtok 函数记录了这是预期的行为。请参阅Notes 部分。相反,编写您自己的标记器,而不是依赖于旧的 C 函数,例如 strtok。 *** 上有很多链接展示了如何创建这样的分词器。 请注意,不能保证recv 会收到在一个send 中发送的所有内容。 TCP/IP 是一个非结构化的八位字节流。 你不能假设socket() 成功了。你不能假设connect() 成功了。你不能假设recv() 成功了。您不能假设 recv() 没有为流结束返回 -1。你不能假设recv() 填满了缓冲区。您不能假设 recv() 收到了整个以空字符结尾的字符串。你不能假设send() 成功了。将strlen() 传递给recv() 是没有意义的。这里的基本错误太多了。 【参考方案1】:

我的问题不是我的 strtok() 函数,在阅读了我的一篇古老的问题后,我意识到我的问题出在 recv() 函数中,我的更正是

recv(sockClient, recvBuf, strlen(recvBuf), 0);

recv(sockClient, recvBuf, sizeof(recvBuf), 0);

这解决了我的问题,最后,我可以从 Python 服务器接收到 C++ 客户端的连续数据。

【讨论】:

以上是关于strtok() 更改我的缓冲区,我需要存储一些在任意时间更改的数据,我该怎么做?的主要内容,如果未能解决你的问题,请参考以下文章

互斥指针可以在锁定状态期间更改吗?

在一定秒数内更改缓冲区大小

使用strtok从字符串中解析空标记

在 Java 中捕获标准输出的内容

更改音频缓冲区的音高

使用统一缓冲区对象进行批量渲染