【问题标题】:Create protocol line from string removing \n and \0从删除 \n 和 \0 的字符串创建协议行
【发布时间】:2020-03-04 23:30:53
【问题描述】:

我们必须用 C 创建一个文本消息 p2p 应用程序。我们已经使用 TCP 接口完成了 p2p 连接,但是我们在实现发送和读取消息的协议时遇到了麻烦。

消息必须采用以下格式:

Line 是我们要发送和阅读的消息。 消息将以 3 个字符开头,以指示行的大小(例如 005)。

然后它将有我们想要写入或读取的行(例如你好)。

所以消息必须是 char t[],在本例中为 005hello。 不必发送或读取 '\n' 或 '\0',只需发送或读取大小和字符串。

我们使用 read() 和 write() 调用系统使用键盘读取和写入消息,因此我们知道我们将要删除 '\n' 和 '\0'。

我们已尝试实现 2 个无法按预期工作的功能。 MI_SendLine(int Socket, const char *Line) 和 MI_ReceiveLine(int Socket, const char *Line)。

MI_SendLine 必须将 *Line 转换为描述的协议,因此行“hello”将转换为“005hello”,“hello\0\n”将转换为“005hello”,“谢谢您的时间\n " 将是 "017thx for your time"。

对于receiveLine函数,我们也有同样的问题,所以代码就省略了。

int MI_SendLine(int Socket, const char *Line)
{
    //PROTOCOL TRANSFORMATION
    //3 chars reserved for size of msg
    char message[3 + strlen(Line)];

    int size = strlen(Line);
    int j;
    for(j = 2; j >= 0; j--){
        message[j] = (size % 10) + '0';
        if(size > 0)
            size /= 10;
    }

    int i;
    for(i = 3; i < strlen(Line) + 3; i++){
      message[i] = Linia[i - 3];
    }

    //END PROTOCOL TRANSFORMATION
    return TCP_Send(Socket, message, sizeof(message));
}

TCP功能,已经测试正常

int TCP_Sent(int Sck, const char *SeqBytes, int LongSeqBytes)
{
    int bytes_written;
    if((bytes_written=write(Sck,SeqBytes,LongSeqBytes))==-1){
        perror("error en write");
        close(Sck);
        exit(-1);
    }

    return bytes_written;
}

我们希望“hello\n”的输出是“005hello”,但实际输出是一个充满未知字符的字符表。

示例: 第一条消息:输入“aaa”收到消息“aaa?”但它不是一个?本身,它是一个包含它的奇怪字符。

2n 消息:输入“b”收到消息“b?.

第三条消息:输入“ccccc”收到消息“ccccc”但没有?

【问题讨论】:

  • 输出是什么?
  • 第一条消息:输入“aaa”收到消息“aaa?”但它不是一个?本身,它是一个包含它的奇怪字符。 2n 消息:输入“b”收到消息“b?。第三条消息:输入“ccccc”收到消息“ccccc”但没有?

标签: c string tcp char c-strings


【解决方案1】:

如果您的意思是如何从没有换行符和零终止符的字符串中获取字符,那么这里有一个演示程序,展示了如何使用标准 C 函数 strcspn 来完成。

#include <stdio.h>
#include <string.h>

int main(void) 
{
    const char *s = "thx for your time\n";
    const size_t Size = 3;
    const size_t Base = 10;

    size_t n = strcspn( s, "\n\0" );

    char result[ Size + n ];

    memcpy( result + Size, s, n );

    for ( size_t i = Size; i != 0; i-- )
    {
        result[i-1] = n % Base + '0';
        n /= Base;
    }


    printf( "\"%*.*s\"\n", ( int )sizeof( result ), 
                           ( int )sizeof( result ), 
                           result );

    return 0;
}

程序输出是

"017thx for your time"

【讨论】:

    【解决方案2】:

    您的代码看起来不错。垃圾必须是接收器中的错误的结果。你忘了附加一个 NUL,或者你有某种非一的错误。

    至于去掉换行,如果最后一个是换行,就缩小大小,少复制一个字符。

    int MI_SendLine(int Socket, const char *Line)
    {
        size_t len = strlen(Line);    
        if (len > 0 && Line[len-1] == '\n')
            --len;
    
        if (len > 999) {
            fprintf(stderr, "Message too big!\n");
            exit(1);
        }
    
        char message[3+len];
        message[0] = '0' + len / 100 % 10;
        message[1] = '0' + len / 10 % 10;
        message[2] = '0' + len % 10;
        memcpy(message+3, Line, len);
        return TCP_Send(Socket, message, 3+len);
    }
    

        // sprintf needs space for a NUL even if we don't send it.
        char message[3+len+1];
        sprintf(message, "%03d%s", len, Line);
        return TCP_Send(Socket, message, 3+len);
    

        char prefix[4];
        sprintf(prefix, "%03d", prefix);
        return TCP_Send(Socket, prefix, 3) + TCP_Send(Socket, Line, len);
    

    请注意,这不会检查字符串中间是否有任何换行符。

    【讨论】:

      猜你喜欢
      • 2018-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-20
      • 2019-10-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多