首页 > 解决方案 > 通过 c 中的套接字从结构中传递字符

问题描述

我正在尝试在我的服务器和客户端之间发送/接收消息。我目前在我的服务器中有一个保存 char 值的结构。我正在尝试将此值传递给我的客户。请参阅以下内容:

tileInfo->tiles[user_cords_x][user_cords_y].identifier = '+'; // Char i want to pass
write_client_msg(cli_sockfd, &tileInfo->tiles[user_cords_x][user_cords_y].identifier);

/* Writes a message to a client socket. */
void write_client_msg(int cli_sockfd, char * msg)
{
    int n = write(cli_sockfd, msg, strlen(msg));
    if (n < 0)
        error("ERROR writing msg to client socket");

}

在我的客户端,我收到以下内容:

char *msg;
char identity = read(sockfd, msg, 1);
printf("This is the value: %d \n", identity);

目前我得到的输出是This is the value: 1. 我是套接字新手,不完全理解传递的字符。有人可以解释一下并告诉我如何将“+”传递给我的客户端吗?

标签: csocketstcpchar

解决方案


您的代码犯了几个错误。

在服务器端,在此代码中:

write_client_msg(cli_sockfd, &tileInfo->tiles[user_cords_x][user_cords_y].identifier);

很明显那identifier是一个单一的char,否则代码将无法编译。在这种情况下,使用strlen()inside ofwrite_client_msg()是错误的,因为msg在传递指向单个 的指针时不会有空终止符char。您最终会将垃圾传输给另一方,如果不是因为访问无效内存而完全崩溃。

然后,在客户端,您将一个未初始化的msg指针传递给read(). 而且,您正在显示read()的返回值,即实际接收到的字节数。这就是您的显示器显示的原因1,因为您要求接收 1 个字节。

要正确发送和接收identifier,您需要更多类似的东西:

void write_client_msg(int sockfd, char *msg, size_t msg_len)
{
    int n = write(sockfd, msg, msg_len);
    if (n < 0)
        error("ERROR writing msg to client socket");
}

...

write_client_msg(cli_sockfd, &tileInfo->tiles[user_cords_x][user_cords_y].identifier, 1);

char identity;
int n = read(sockfd, &identity, 1);
if (n < 0)
    error("ERROR reading identity from client socket");
else if (n == 0)
    error("DISCONNECTED while reading identity from client socket");
else
    printf("This is the value: %c \n", identity);

话虽如此,更好的解决方案是在write_client_msg()发送. 特别是因为不知道它正在发送什么样的数据。然后客户端可以读取以知道要为 读取多少字节,然后根据需要处理 。msg_lenmsgwrite_client_msg()msg_lenmsgmsg

此外,write()并且read()可以返回比请求更少的字节,因此您需要在循环中调用它们以确保您实际发送/接收所有内容。

例如:

int write_all(int sockfd, void *data, size_t data_len)
{
    char *d = (char*) data;
    while (data_len > 0)
    {
        int n = write(sockfd, d, data_len);
        if (n < 0)
            return n;
        d += n;
        data_len -= n;
    }
    return 1;
}

void write_client_msg(int sockfd, char *msg, size_t msg_len)
{
    uint32_t len = htonl(msg_len);
    int n = write_all(sockfd, &len, sizeof(len));
    if (n == 1)
        n = write_all(sockfd, msg, msg_len);
    if (n < 0)
        error("ERROR writing msg to client socket");
}

...

write_client_msg(cli_sockfd, &tileInfo->tiles[user_cords_x][user_cords_y].identifier, 1);

int read_all(int sockfd, void *data, size_t data_len)
{
    char *d = (char*) data;
    while (data_len > 0)
    {
        int n = read(sockfd, d, data_len);
        if (n <= 0)
            return n;
        d += n;
        data_len -= n;
    }
    return 1;
}

char *read_server_msg(int sockfd)
{
    uint32_t len;
    int n = read_all(sockfd, &len, sizeof(len));
    if (n <= 0)
        return NULL;
    len = ntohl(len);
    char *msg = malloc(len+1);
    if (!msg)
        return NULL;
    n = read_all(sockfd, msg, len);
    if (n <= 0) {
        free(msg);
        return NULL;
    }
    msg[len] = '\0';
    return msg;
}

...

char *msg = read_server_msg(sockfd);
if (!msg)
    error("ERROR reading msg from client socket");
else {
    printf("This is the value: %s \n", msg);
    free(msg);
}

推荐阅读