套接字编程C,接收到的消息正在从先前的消息转移过来

时间:2018-09-22 01:44:15

标签: c sockets pointers char

嗨,我正在尝试在服务器和客户端应用程序之间创建一个简单的用户名/密码读写。目前,我的客户端运行良好。我遇到的问题在服务器端内部。当我在客户端输入用户名时,服务器会正​​确捕获该用户名。请参见以下代码:

void authenticate_process(int cli_sockfd){

    /* Authentication Process */
    write(cli_sockfd, "USN", 3);
    char *username;
    username = recv_msg(cli_sockfd);
    printf("[DEBUG] Client username is %s.\n", username);

    write(cli_sockfd, "PSW", 3);
    char *password;
    password = recv_msg(cli_sockfd);
    printf("[DEBUG] Client Password is %s.\n", password);

}

问题是例如用户输入“ Johnabscaras”作为用户名,然后代码将最后一个“ ras”放入密码变量中。我的recv_msg函数如下所示:

/* Reads a message from the server socket. */
char *recv_msg(int sockfd)
{
    int length;
    char *msg;
    msg = (char*) malloc (9);

    /* All messages are 9 bytes. */
    int n = read(sockfd, msg, 9);
    return msg;

}

由于用户名和密码从不大于9个字节,因此为此进行了设置。但是我发现,如果您首次输入用户名,并且键入的字符数超过9个,则多余的字符将被修改为password变量。如果您输入的字符少于9个,则代码会跳过,并且出于某种原因,密码变量会立即设置为“”。有人可以解释一下,告诉我如何解决吗?

1 个答案:

答案 0 :(得分:0)

您似乎正在使用流套接字(SOCK_STREAM,即TCP)。从应用程序的角度来看,流套接字基本上只是一个双向管道。

除了您的应用程序强加的内容外,没有“消息”的概念。套接字仅发送和接收单个长字节流。 write(fd, "foo", 3); write(fd, "bar", 3);write(fd, "foobar", 6);具有相同的作用。它以相同的顺序发送相同的字节。

如果您希望流传输多条单独的消息,则必须以某种方式对这些消息边界进行编码。

  • 例如,您可以确定每条消息正好是100个字节长,然后始终发送/接收正好是100个字节。
  • 或者您可以使用显式终结符(例如'\0')标记消息的结尾。然后,接收到的代码将不得不循环直到看到'\0'
  • 或者您可以发送长度字段作为每封邮件的第一部分;这样接收代码就可以提前知道需要分配和读取多少字节。

您的代码中的此注释表示您选择了选项1:

/* All messages are 9 bytes. */

但是显然,发送代码有一个错误,因为它试图传输一条9字节以上的消息,然后将其解释为多条消息。如果客户端发送12个字节,则该消息为9个字节,然后是另一个(不完整的)3个字节的消息。 “ 当前我的客户端运行正常”?不,不是;不是。至少在您的接收码正确的情况下不是。

另一个问题是

printf("[DEBUG] Client username is %s.\n", username);

%s需要一个C字符串,即一个以N终止的字符序列。 username没有NUL终止符(除非客户端决定显式发送'\0'字节作为消息的一部分)。实际上,recv_msg的用户无法知道收到了多少数据。如果总是9个字节,

printf("%.9s", username);

可以工作,但是recv_msg不能确保确实如此:

int n = read(sockfd, msg, 9);

它只是忽略了n,因此msg的全部或部分可能未初始化,并且调用代码无法分辨。