Вы делаете несколько ошибок с вашим кодом.
На стороне сервера, в этом коде:
write_client_msg(cli_sockfd, &tileInfo->tiles[user_cords_x][user_cords_y].identifier);
Понятно, что identifier
является единственным char
,иначе код не скомпилируется.В этом случае использование strlen()
внутри write_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_len
перед отправкой msg
.Тем более, что write_client_msg()
не знает, какие данные он отправляет.Затем клиент может прочитать msg_len
, чтобы узнать, сколько байтов нужно прочитать для msg
, а затем обработать msg
при необходимости.
Кроме того, 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);
}