htonl / ntohl在第二个命令上的值不正确?

时间:2015-03-05 19:07:55

标签: c sockets htonl

编辑:老实说,我不知道错误发生在哪里,所以我只是添加大部分相关代码,不确定是否有任何帮助

基本上我有两个基本的服务器&客户流程。 用户指定命令,客户端进程然后将消息的长度发送到服务器,服务器执行命令并发回响应的消息长度。

这适用于第一个命令(我连续尝试了两个ls -la),第一个命令(正确值)的值为1028,第二个命令的值为1685223288(在客户端中)

使用以下代码完成写入:

server_handler() {
char str[5000];
char * token = NULL;
unsigned long totalSize = 0;
str[0] = "\0";
totalSize = htonl(totalSize); // Correct size already calculate
if((result = write(clientFD, (char *) &totalSize, sizeof(totalSize)) < 0))
{
     printf("Failed sending size to client\n");
     exit(-1);
}
//Here the server starts sending the results to the client
token = strtok(str, "\n"); // str array contains the results
while(token != NULL)
{
     token[strlen(token)] = '\n';
     write(clientFD, token, strlen(token));
     token = strtok(NULL, "\n);
}

通过以下方式在客户端进程中完成读取:

static void handle_reply() 
{
char * revBuf = 0;
unsigned long int bytesRead = 0;
unsigned long bufferlen = 0;
while(1) 
{
    result = read(socketFD, (char *) &bufferlen, sizeof(bufferlen));
    bufferlen = ntohl(bufferlen);
    recvBuf = malloc(bufferlen);
   //Here client starts reading results
    while(bytesread < bufferlen)
    {
        result = read(socketFD, recvBuf, bufferlen);
        printf("recvBuf: %s\n", recvBuf);
        bytesRead = strlen(recvBuf) + bytesRead;
    }
    free(recvBuf);
    bufferlen = 0;
   client_handler(); //calls Function that asks for new command
}
}

我的问题:为什么我在第一个命令后收到错误的命令值? 我已经验证了在两种打印情况下,totalSize在服务器端都具有正确的值。 在写/读中一定有问题吗?

我还在服务器上打印了htonl(totalSize),它是67371008。 但是,在ntohl之前,客户端收到的价值是2021093988。

2 个答案:

答案 0 :(得分:1)

以下代码无法正常运行,因为您在修改字符串后再次调用strlen

token = strtok(str, "\n");
while(token != NULL)
{
    token[strlen(token)] = '\n';
    write(clientFD, token, strlen(token));
    token = strtok(NULL, "\n");
}

为了说明,假设str最初是"hello\nworld\n"。在十六进制中

 68 65 6c 6c 6f 0A 77 6f 72 6c 64 0A 00
                ^---- the first newline

strtok之后

 68 65 6c 6c 6f 00 77 6f 72 6c 64 0A 00
                ^---- strtok changed it to a NUL

token[strlen(token)] = '\n'行后,它将是

 68 65 6c 6c 6f 0A 77 6f 72 6c 64 0A 00
                ^---- you changed it back to a newline

所以现在strlen中的write将返回12,因此write将发送12个字节,而不是像您期望的那样发送6个字节。这可以通过调用strlen一次来修复,就像这样

token = strtok(str, "\n");
while(token != NULL)
{
    size_t length = strlen(token);
    token[length] = '\n';
    write(clientFD, token, length);
    token = strtok(NULL, "\n");
}

答案 1 :(得分:0)

htonl和ntohl是32位...

  uint32_t htonl(uint32_t hostlong);
  uint32_t ntohl(uint32_t netlong);

使用64位系统查看该程序的大整数会发生什么。

#include <stdio.h>

int main(int argc, char** arg)
{
  unsigned long bufferlen = 0;
  unsigned long totalSize = 1024;
  sscanf(arg[1],"%lld",&totalSize);
  printf("%lld  %llx\n", totalSize,totalSize);

  totalSize = htonl(totalSize); // 32 <-> 64bits .
  bufferlen = ntohl(totalSize);

  printf("%lld %llx %lld %llx\n", totalSize,totalSize,bufferlen,bufferlen);

}

测试它:

./test 111111111111111
111111111111111  650e124ef1c7
-940487150 ffffffffc7f14e12 307163591 124ef1c7