我正在编写一个简单的客户端/服务器应用程序,但遇到了一个非常奇怪的问题。
我正在尝试向客户端发送一个 .zip 文件,然后再发送一些数据。 发送 .zip 工作正常,服务器写入套接字,客户端从套接字读取,正如预期的那样。
问题紧随其后。 服务器运行良好并不断写入套接字,但客户端不会读取任何内容。无论我尝试发送什么,它都会卡在下一个 read() 调用上。
我已经检查过套接字描述符是否正常,确实如此。我也想过可能是socket里面的数据不够client读取,但是肯定是有的。
我还尝试在发送该 .zip 文件之前和之后执行相同的写入/读取操作:之前它工作正常,但客户端在发送该文件之后看不到它。压缩。 我没主意了。
这是我用来发送 .zip 的函数:
typedef struct thData{
int idThread; //thread ID
int cl; //client descriptor
}thData;
void send_info(struct thData tdL)
{
char file_path[256]="v1.zip";
char sd_buffer[256];
bzero(sd_buffer, 256);
FILE *fd = fopen(file_path, "rb");
if(fd == NULL)
{
printf("ERROR: %s not found.\n", file_path);
exit(1);
}
int read_size;
int write_size;
while((read_size = fread(sd_buffer, sizeof(char), 256, fd)) > 0)
{
if((write_size=write(tdL.cl, sd_buffer, read_size)) < 0)
{
perror("ERROR: writing to client: \n");
break;
}
bzero(sd_buffer, 256);
}
}
以及我用来接收 .zip 的内容:
void receive_info(int sd) //sd being the socket descriptor
{
char* file_path = "subject.zip";
char received_buffer[256];
int total_received=0;
int total_wrote=0;
FILE *fd = fopen(file_path, "wb");
if(fd == NULL)
printf("Cannot open %s\n", file_path);
else
{
bzero(received_buffer, 256);
int read_size = 0;
while((read_size = read(sd, received_buffer, 256)) > 0)
{
total_received=total_received+read_size;
int write_size = fwrite(received_buffer, sizeof(char), read_size, fd);
total_wrote=total_wrote+read_size;
if(write_size < read_size)
{
perror("ERROR: \n");
}
bzero(received_buffer, 256);
if (read_size == 0 || read_size != 256)
{
break;
}
}
if(read_size < 0)
{
perror("ERROR: reading: ");
exit(1);
}
fclose(fd);
}
}
如有任何帮助,我们将不胜感激。
最佳答案
我认为问题是你读得太多了。
在 TCP 中,从一个点发送到另一个点的数据包没有边界。它只是一个字节流,从 recv/read()
接收的片段与从 send/write()
发送的片段没有关系(原则上)。
现在,假设您的 ZIP 文件有 300 个字节长,而您的额外数据有 10 个字节长。您的发件人代码将执行以下操作:
- 写入 256 个字节(ZIP 中的第一部分)。
- 写 44 个字节(ZIP 的最后一段)。
- 写入 10 个字节(额外数据)。
您的接收器代码将执行以下操作:
- 读取 256,得到 256 个字节(ZIP 中的第一部分)。
- 读取 256,得到 54 个字节(ZIP 的最后一段加上额外数据)。
- 读取XXX字节,永远等待!
如果仔细查看 ZIP 文件,您可能会在 subject.zip
的末尾看到那些额外的字节。
如果您不想关闭并打开另一个套接字,解决方案是使协议(protocol)更复杂一些。例如,您可以在包含文件大小的文件(标题)之前发送一个结构。这样接收方就会知道何时停止阅读。
PS:请注意,您的代码存在一些风险。例如,write()
可能不会写入所有给定的字节,但您没有检查它;你没有关闭文件...
PS2:我很好奇你觉得需要写 sizeof(char)
而不是 1
但是你写 256
而不是sizeof(sd_buffer)
。
关于客户端读取另一个文件后没有读取任何数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34842604/