只有当我用自己的计算机执行此操作时它才有效,但是当我使用另一台计算机时,收到的文件一团糟,而且大小始终是另一个。
服务器:
while (1) {
ZeroMemory(r_buf, MAX_BUFF_RECV - 1);
bytesReceived = recv(sock, r_buf, FILE_DOWNLOAD_SIZE, 0);
if (bytesReceived < 0) {
// ERROR
puts("[!] recv failed");
return;
}
else if (bytesReceived < FILE_DOWNLOAD_SIZE) {
// LAST CHUNCK
if (WriteFile(out, r_buf, bytesReceived, &n, NULL) == FALSE) {
printf("WriteFile() error %d\n", GetLastError());
}
break;
}
else {
if (WriteFile(out, r_buf, bytesReceived, &n, NULL) == FALSE) {
printf("WriteFile() error %d\n", GetLastError());
}
}
}
客户:
while (1)
{
ZeroMemory(buff, FILE_DOWNLOAD_SIZE);
nread = fread(buff, 1, FILE_DOWNLOAD_SIZE, f);
if (nread != FILE_DOWNLOAD_SIZE) {
send(s, buff, nread, 0);
break;
}
else {
send(s, buff, nread, 0);
}
}
我花了几个小时,请告诉我出了什么问题
最佳答案
在面向连接的传输中,例如 TCP,send()
和 recv()
不是一对一的。无法保证您 send()
会在单个数据包中传输,也不保证 recv()
会收到您 send()< 的所有内容
一次完成。
无法保证 send()
会接受您提供的所有内容。它将尽可能地将所有内容复制到套接字的出站缓冲区中,并返回实际复制的字节数。因此它可以接受比请求更少的字节。
同样,recv()
将复制套接字入站缓冲区中当前可用的任何数据,至少 1 个字节,但不超过将指定的字节数放入指定的缓冲区中,并将返回复制的实际字节数。因此它可以接收比请求更少的字节。
您还需要知道实际传输了多少文件数据,以便知道何时停止读取数据。由于 recv()
返回的字节数少于请求的字节数,因此您不能仅依靠缓冲区大小来指示 EOF。
您没有在代码中考虑到这些。
尝试更多类似这样的事情:
服务器:
bool readRaw(SOCKET sock, void *buf, int bufSize)
{
char *pbuf = (char*) buf;
while (bufSize > 0)
{
int bytesReceived = recv(sock, pbuf, bufSize, 0);
if (bytesReceived < 0)
{
printf("[!] recv() error %d\n", WSAGetLastError());
return false;
}
else if (bytesReceived == 0)
{
puts("[!] client disconnected");
return false;
}
else
{
pBuf += bytesReceived;
bufSize -= bytesReceived;
}
}
return true;
}
...
unsigned __int64 fileSize = 0;
if (readRaw(sock, &fileSize, sizeof(fileSize)))
{
while (fileSize > 0)
{
int bufSize = min(fileSize, MAX_BUFF_RECV);
if (!readRaw(sock, r_buf, bufSize))
break;
if (!WriteFile(out, r_buf, bufSize, &n, NULL))
{
printf("[!] WriteFile() error %d\n", GetLastError());
break;
}
fileSize -= bufSize;
}
}
客户:
bool sendRaw(SOCKET sock, void *buf, int bufSize)
{
char *pbuf = (char*) buf;
while (bufSize > 0)
{
int bytesSent = send(sock, pbuf, bufSize, 0);
if (bytesSent < 0)
{
printf("[!] send() error %d\n", WSAGetLastError());
return false;
}
else
{
pBuf += bytesSent;
bufSize -= bytesSent;
}
}
return true;
}
...
fseek(f, 0, SEEK_END);
long int pos = ftell(f);
fseek(f, 0, SEEK_SET);
if (pos == -1)
printf("[!] ftell() error\n");
else
{
unsigned __int64 fileSize = pos;
if (sendRaw(s, &fileSize, sizeof(fileSize)))
{
while (fileSize > 0)
{
int bufSize = min(FILE_DOWNLOAD_SIZE, fileSize);
nread = fread(buff, 1, bufSize, f);
if (nread == 0)
{
printf("[!] fread() error\n");
break;
}
if (!sendRaw(s, buff, nread))
break;
uifileSize -= nread;
}
}
}
关于无法通过套接字 C 发送文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32285485/