【发布时间】:2010-12-16 19:09:15
【问题描述】:
我有一个服务器和一个客户端程序(都在同一台机器上运行)。客户端能够向服务器发送一个带有“ID”、“size”等成员的结构。然后我希望服务器将 ID 成员(只是一个整数)作为 ACK 发送回客户端以进行验证,但是尽管能够毫无问题地发送结构,但我还是无法弄清楚..
这是来自 server.c 的代码:
/* having just recieved the struct */
int ACK_ID = struct_buffer->message_ID;
result = send(CLIENT_socket, &ACK_ID, sizeof(int), 0);
if (result == -1) {
close(SERVER_socket);
printf("\n\t[ERROR] Failed to send ACK.\n");
exit(EXIT_FAILURE);
}
这是来自 client.c 的代码:
// Recieve ACK from server
int ACK_ID;
com_result = read(CLIENT_socket, &ACK_ID, sizeof(int), 0);
if ((com_result == -1) || (ACK_ID != metablocks[index].message_ID)) {
printf("\n\t[ERROR] Failed to send metadata. ACK: %i\n", ACK_ID);
}
当我尝试运行它时,我从 client.c 得到以下输出:
[错误] 无法发送元数据。确认:14
当然,服务器告诉我它发送 ACK 失败。我尝试发送的 ID 整数的值应该是 1,但接收到的是 14。我在这里做错了什么?
更新
所以我只是尝试了Shawley先生的建议,并得到了这个错误信息:
部分读取:未定义错误:0
首先我完全尝试了他写的内容,但后来我注意到代码将com_result 与sizeof(int) 进行比较。所以我认为这是一个错字,并尝试在比较中用ACK_ID 变量替换com_result。结果一样。
更新 2
刚刚失败时在服务器上加了一个perror(),得到如下错误信息:
错误的文件描述符
我在此操作中使用与接收结构时使用的相同的套接字。这是来自 server.c 的扩展代码示例:
// Recieve connection
CLIENT_socket = accept(SERVER_socket, (struct sockaddr *)&CLIENT_address, &CLIENT_address_length);
if (CLIENT_socket == -1) {
close(SERVER_socket);
printf("\n\t[ERROR] Failed to accept client connection.\n");
exit(EXIT_FAILURE);
}
printf("\n\tClient connected!\n");
int data_size;
// Read meta data from connection
data_size = sizeof(struct msg_meta);
result = read(CLIENT_socket, &meta_buffer_char, data_size, 0);
meta_buffer = (struct msg_meta *) meta_buffer_char;
if (result == -1) {
close(SERVER_socket);
printf("\n\t[ERROR] Failed to read from connection.\n");
perror("\n\tRead");
exit(EXIT_FAILURE);
} else if (result > 0) {
printf("\n\tMessage recieved.\n");
printf("\n");
}
// Send ACK back to client
int ACK_ID = meta_buffer->message_ID;
result = send(CLIENT_socket, &ACK_ID, sizeof(int), 0);
if (result == -1) {
printf("\n\t[ERROR] Failed to send ACK.");
perror("\n\tSend");
printf("\n");
close(SERVER_socket);
exit(EXIT_FAILURE);
}
// Close sockets
close(SERVER_socket);
close(CLIENT_socket);
【问题讨论】:
-
旁白:在发送和接收(分别)一个 int 时使用
htonl和ntohl以确保它具有正确的字节顺序。 -
在打印网络错误(如果有)之前无法确定。您还可以验证发送到服务器的原始结构实际上是否包含您期望的值。
-
@outis: 不,看同一个人的问题stackoverflow.com/questions/1734819/…。他知道他在便携性方面处于犯罪状态。用 little-endian 整数定义有线协议没有任何问题,如果他想要 big-endian 客户端或服务器,他只需要更改它(或开始字节交换)。
-
结构在服务器上被验证。我知道我正在将正确的数据发送回客户端..
-
Shawley 先生假设您的发送成功,但您的问题是 服务器告诉我它发送 ACK 失败 在服务器端也尝试
perror。 (顺便说一句,如果服务器发送 ACK 失败,部分读取是相当奇怪的!)
标签: c macos tcp sockets integer