c - 解析来自套接字的单个消息,其中包含 C 中的 2 个字符串

标签 c sockets buffer

我正在尝试读取包含 2 个字符串的消息。该消息包含 2 个字符串,可以是任何内容,并且通过套接字发送。

请注意,我在 Ubuntu 环境中使用 C。

消息的格式是,在单个void*缓冲区中:

[字符串1]\0[字符串2]\0

我想一旦它们到达我就能够将它们分开,使用“\0”来找出在哪里分割它们。我正在使用一个函数来读取字符串,它确实有效,但我不断收到 Valgrind 的提示,我不明白为什么。

我将使用一个仅从缓冲区读取 1 个字符串的示例,但我提到该策略是因为我无法将消息放入 char* 缓冲区。我需要该函数从更复杂的缓冲区中提取字符串。

一切都是这样开始的:

void* buffer = malloc(msgSize * sizeof(char)); //the message size is properly calculated to include the '\0' at the end
char* instanceId = malloc(msgSize * sizeof(char));

if(recv(socket_desc, (void*) buffer, msgSize * sizeof(char), MSG_WAITALL) <= 0) {
        log_error(logger, "Message failed.");
        return;
    }

    bufferToString(buffer, &instanceId, 0);
    bufferToString2(buffer, instanceId, 0);

我做了几次尝试让 bufferToString 工作,正如你所看到的......当然我不会同时调用它们,但我想分享这些行,以防我在那里犯错误。

尝试#Number 1:逐个字符

int bufferToString(void* buffer, char** string, int startPtr) {
    //startPtr can be used to read strings that are in the middle of a buffer
    char a;
    int thisStringPtr = 0; 

    do {
        a = *(char*) (buffer + startPtr);
        (*string)[thisStringPtr] = a;
        startPtr++;
        thisStringPtr++;
    } while (a != '\0');
    return startPtr; //return end position to use for extracting more values later

}

这个人提示:

==23047== Invalid read of size 1
==23047==    at 0x403A27A: bufferToString (buffer.c:16)
==23047==    by 0x804A0C2: handleHiloInstancia (coordinador.c:232)
==23047==    by 0x8049C54: procesarConexion (coordinador.c:85)
==23047==    by 0x4066294: start_thread (pthread_create.c:333)
==23047==    by 0x41650AD: clone (clone.S:114)
==23047==  Address 0x423bc8a is 0 bytes after a block of size 10 alloc'd
==23047==    at 0x402C17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==23047==    by 0x804A063: handleHiloInstancia (coordinador.c:225)
==23047==    by 0x8049C54: procesarConexion (coordinador.c:85)
==23047==    by 0x4066294: start_thread (pthread_create.c:333)
==23047==    by 0x41650AD: clone (clone.S:114)

bufferToString 的第 16 行是 do 语句内的第一行。

尝试 2:转换和复制

int bufferToString2(void* buffer, char* string, int startPtr) {
    strcpy(string, (char*) (buffer + startPtr));
    return (strlen(string) + 1)*sizeof(char);
}

无论有没有+startPtr,这都会导致略有不同的问题:

==23190== Invalid read of size 1
==23190==    at 0x402F489: strcpy (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==23190==    by 0x403A1E3: bufferToString2 (buffer.c:3)
==23190==    by 0x804A0C1: handleHiloInstancia (coordinador.c:232)
==23190==    by 0x8049C54: procesarConexion (coordinador.c:85)
==23190==    by 0x4066294: start_thread (pthread_create.c:333)
==23190==    by 0x41650AD: clone (clone.S:114)
==23190==  Address 0x423bc8a is 0 bytes after a block of size 10 alloc'd

我尝试了一些其他组合(例如使用 char** 字符串以及 bufferToString2 中的所有必需修改),但我不断收到类似的错误消息。我没看到什么?

更新:消息如何发送:

    int bufferSize;
    void* buffer = serializePackage(HANDSHAKE_INSTANCE_ID ,instancia_config->nombre, &bufferSize );
    printf("Buffer size: %i - Instancia Name = %s - Socket num: %i\n", bufferSize, instancia_config->nombre, socket_coordinador); //this shows right data
    if (send(socket_coordinador,buffer,bufferSize, 0) <= 0) {
        log_error(logger, "Could not send ID.");
        endProcess(EXIT_FAILURE);
    }

instancia_config->nombre 的类型为 char*

void* serializePackage(int codigo,char * mensaje, int* tamanioPaquete){

    int puntero = 0;
    int length = strlen(mensaje);

    int sizeOfPaquete = strlen(mensaje) * sizeof(char) + 1 + 2 * sizeof(int);
    void * paquete = malloc(sizeOfPaquete);


    memcpy((paquete + puntero) ,&codigo,sizeof(int));
    puntero += sizeof(int);

    memcpy((paquete + puntero),&length,sizeof(int));
    puntero += sizeof(int);

    memcpy((paquete + puntero),mensaje,length * sizeof(char) + 1);

    *tamanioPaquete = sizeOfPaquete;
    return paquete;

}

最佳答案

你的 src 和 dst 正确吗? C 中内存服务的目的地(或目标,如果您愿意)是第一个参数,因此: strcpy(字符串,缓冲区) 将缓冲区复制到字符串中。 (https://www.tutorialspoint.com/c_standard_library/c_function_strcpy.htm)

但是:使用 buffer 作为第一个参数调用 bufferToString2(在本例中它是源)。

在第一种情况下,正如所指出的,你不能对 void* 进行算术运算,因为如果你说: *(x+N) 如果 x 为“void”,则它没有大小,因此第 N 个元素没有意义。

关于c - 解析来自套接字的单个消息,其中包含 C 中的 2 个字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50730178/

相关文章:

c - 感知器学习算法不收敛到 0

c - 有什么办法可以用我自己的 softirq 调用 linux 内核

python - 使用root,打开其他进程套接字并使用python获取tcp_info?

c++ - 套接字发送数据但 recv 程序不能正常工作

javascript - 在 discord.js 中发送文件缓冲区

c - 确定使用哪种 sockaddr 变体的正确方法是什么?

c - 确定处理器的字长

c# - 2个线程处理异常行为的套接字

c - 如何修复创建缓冲区并将其直接写入磁盘(WriteFile)

ios - 如何确定AVAssetWriter中样本缓冲区使用的持续时间