Clinet端的read()获取到消息的随机尾随字符(使用套接字的TCP客户端-服务器)

时间:2019-01-06 07:40:46

标签: c sockets tcp

实践C网络编程:我正在编写一个简单的TCP客户端-服务器应用程序,该应用程序应该将消息(作为每个客户端的单独线程)作为字符串从服务器发送到客户端,并将消息打印在客户端(稍后将成为控制台商店应用)。我首先发送消息的大小,然后使用套接字write()函数发送消息本身。服务器端:

void answer(void *arg) {
    struct thData tdL; 
    tdL= *((struct thData*)arg);

    // Welcome message
    char *initMsgToClient;
    getInitialMessage(&initMsgToClient);
    int len_initMsgToClient = strlen(initMsgToClient);

    // Returning message to client
    if ( write (tdL.cl, &len_initMsgToClient, sizeof(int)) <= 0 ) {
         printf("[Thread %d] ",tdL.idThread);
         perror ("[Thread] Error at write(): len_initMsgToClient to client.\n");
    }
    if (write (tdL.cl, initMsgToClient, len_initMsgToClient) <= 0) {
         printf("[Thread %d] ",tdL.idThread);
         perror ("[Thread]Error at write(): initMsgToClient to client.\n");
    }
    else
        printf ("[Thread %d] Message was sent with success.\n",tdL.idThread);

}

void getInitialMessage(char **paramMessage) {
    char *resultMessage = "Welcome to Console Shopper!";
    *paramMessage = resultMessage; 
}

在客户端,我首先读取大小,然后读取消息本身并进行打印,但是每次运行./client时,消息中都会得到不同的随机尾随字符。客户端:

char welcomeMessageFromServer[512];
int lenWelcomeMsg;
// Reading size of first mesage: lenWelcomeMsg
if (read(sd, &lenWelcomeMsg, sizeof(int)) < 0) {
    perror ("[client] Error reading len welcome message from server.\n");
}
// Reading initial message from server: welcomeMessageFromServer
if (read(sd, welcomeMessageFromServer, lenWelcomeMsg) < 0) {
    perror ("[client] Error reading welcome message from server.\n");
    return errno;
}
printf("%s",welcomeMessageFromServer);
printf("\n");

为简单起见,我省略了添加套接字和线程处理的代码,大多数代码来自教程,因此应该是正确的。我很确定自己在发送/接收的消息大小方面做错了。 我的输出针对./client进行了多次运行:

Welcome to Console Shopper!
Welcome to Console Shopper!�
Welcome to Console Shopper!������i0  
Welcome to Console Shopper!������UF+:  

有时候它会正确。为了始终获得正确的消息,我应该纠正什么?

1 个答案:

答案 0 :(得分:1)

// Reading initial message from server: welcomeMessageFromServer
if (read(sd, welcomeMessageFromServer, lenWelcomeMsg) < 0) {
    perror ("[client] Error reading welcome message from server.\n");
    return errno;
}
printf("%s",welcomeMessageFromServer);

您在这里有两个问题:

  1. %s格式说明符仅用于C样式的字符串。要使收到的消息成为C样式的字符串,您需要在其末尾添加一个终止的零字节。

  2. read函数不能确保它接收到所有请求的字节。您需要检查返回值,如果未收到完整的消息,请再次调用它。

尝试这样的功能:

ssize_t readAll (int fd, void *vbuf, size_t count)
{
     char *buf = (char *) vbuf;
     ssize_t read_so_far = 0;
     while (count > 0)
     {
         ssize_t ret = read(fd, buf, count);
         if (ret < 0)
             return ret;
         if (ret == 0)
             return read_so_far;
         count -= ret;
         read_so_far += ret;
         buf += ret;
     }
     return read_so_far;
}

然后您可以执行以下操作:

// Reading initial message from server: welcomeMessageFromServer
if (readAll(sd, welcomeMessageFromServer, lenWelcomeMsg) != lenWelcomeMsg) {
    perror ("[client] Error reading welcome message from server.\n");
    return errno;
}
welcoemMessageFromServer[lenWelcomeMsg] = 0;
printf("%s",welcomeMessageFromServer);