繁体   English   中英

read()函数中的随机空字符

[英]Random null chars in read() function

我正在用TCP构建基本的客户端和服务器。 它工作正常,除非密钥变大。 它只是来回发送密钥,直到时间结束。 当它变大(又名4096)时,read()语句将随机获得一个null,然后将密钥分为两个msg,这将破坏循环。

我真的不确定为什么要这样做,因为服务器代码已经在其他客户端上进行了测试,所以该代码正在运行,所以我的客户端出了点问题。 任何想法(很短):

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h> 

#define BUFFER_LENGTH 5120

// Error message taken from reference
void error(const char *msg)
{
    printf("%s\n", msg);
    exit(0);
}
int main(int argc, char *argv[])
{
    int sockfd, portNumber, n;
    struct sockaddr_in serv_addr;
    struct hostent *server;

    // Invalid arguments
    if (argc < 4)
        exit(0);
    else if (atoi(argv[3]) < 1 || atoi(argv[3]) > 4096)
        exit(0);

    char buffer[BUFFER_LENGTH];
    bzero(buffer, BUFFER_LENGTH);
    char buffer2[BUFFER_LENGTH];
    bzero(buffer2, BUFFER_LENGTH);
    strcpy(buffer2, "Connect.  Key length:  ");
    strcpy(buffer, strcat(buffer2, argv[3]));
    portNumber = atoi(argv[2]); // Get port number in int format
    sockfd = socket(AF_INET, SOCK_STREAM, 0); // Create socket connection to server using internet constants

    // Did we open the socket succesfully?
    if (sockfd < 0)
        error("Error opening socket.");

    // Is the IP Address valid?
    server = gethostbyname(argv[1]);
    if (server == NULL)
        error("Could not connect to server. Terminating.");

    // Initialize to zero and then set
    // Taken from reference
    bzero((char *) &serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);
    serv_addr.sin_port = htons(portNumber);
    if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) 
        error("Could not connect to server. Terminating.");

    short connected = 1;
    do 
    {
        // Send initial request on first pass
        // Afterwards send the resposne we were given
        printf("Sending: %s\n", buffer);
        printf("Length of msg: %d\n", (strlen(buffer) + 1));
        n = write(sockfd, buffer, strlen(buffer) + 1);
        if (n < 1) 
             error("Failed to send Message. Terminating.");

        // Get session key response
        bzero(buffer, BUFFER_LENGTH);
        n = read(sockfd, buffer, BUFFER_LENGTH);
        if (n < 1)
            error("Could not fetch result.  Terminating.");

        // Stop
        if (strcmp(buffer, "Invalid session key.  Terminating.") == 0)
            break;

        printf("%s\n", buffer);
        sleep(1);
    } while (connected == 1);

    // Done (this should never be reached in this client)
    error("Could not fetch result.  Terminating.");
    close(sockfd);
    return 0;
}

不要在二进制数据上使用strcpy()或任何str*()函数。 您不处理字符串。 使用memcpy()并指定要复制的字节数。

str*()函数对字符串进行操作; C标准将字符串定义为“由第一个空字符终止并包括第一个空字符的连续字符序列”。 但是在二进制数据中,空字符(零字节)只是另一块数据,不一定具有任何意义。

如果您的二进制数据看起来像这样(十六进制):

4b d9 e7 b3 00 96 89 fb

然后strcpy()将忽略00字节之后的所有内容。 更糟糕的是,如果您的二进制数据如下所示:

4b d9 e7 b3 2f 96 89 fb

如果没有空字节,则strcpy()strlen() ,或者任何字符串函数将继续通过缓冲区的末尾,从而产生不可预测的结果。

您假设一个write()发送的数据正好被一个read() TCP或Sockets API规范中没有任何东西支持此假设。 您必须阅读直到获得完整的消息为止,并且“消息”是由您定义的,而不是由TCP或API定义的。

仅出于调试目的,也许write()read()之间的sleep()会有所帮助,以便让服务器有时间进行响应? 从长远来看,配置适当的超时将是正确的处理方式。 再说一次,我可能走错了路。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM