我正在尝试使用 C++ 中的 UDP 套接字在客户端和服务器之间发送数据,作为我大学中的一个项目。我尝试发送的文件是一个名为
s.html
的 HTML 文档。大小为 1,814,247 字节。
发送文件时,我在客户端看到两个不同的数字,第一个是接收到的总字节数减去每个数据包标头的大小 - 即 8 个字节。
它说我收到了1,814,239字节“在右侧终端写入的数字”。因此,接收函数中缺少 8 个字节。
更大的问题是,当我尝试检查其目录中的文件大小时,它给了我1,810,500字节,这与真实数字相距甚远。
数据包、数据包和确认包的结构:
struct ack_packet {
uint16_t chsum;
uint16_t len;
uint16_t ackno;
};
struct packet {
uint16_t chsum;
uint16_t len;
uint16_t seqno;
uint16_t finished;
char data[500];
};
这是感兴趣的服务器部分的代码,如果还不足以让您理解问题,请告诉我,我将上传整个代码。
const size_t chunkSize = 500;
for (uint16_t seqno = 0; seqno < fileSize / chunkSize; ++seqno) {
packet pkt;
pkt.seqno = (seqno);
pkt.len = (chunkSize+8);
pkt.chsum = 88; // random now
pkt.finished = 88; // not 1
memcpy(pkt.data, fileContent.data() + seqno * chunkSize, chunkSize);
if(seqno == fileSize / chunkSize - 1 && fileSize % chunkSize == 0)
pkt.finished = 1;
/**
* The real business starts*/
ssize_t b = sendto(newSock, &pkt, pkt.len, 0, &clntAddr, clntAddrLen);
if(b < 0)
perror("sendto() failed");
ack_packet receivedPacket{};
recvfrom(newSock, (void*)&receivedPacket, 6, MSG_WAITALL,&clntAddr, &clntAddrLen);
if((receivedPacket.ackno) != seqno){
seqno--;
}
}
size_t lastChunkSize = fileSize % chunkSize;
if (lastChunkSize > 0) {
packet pkt;
pkt.seqno = fileSize / chunkSize; // Finished
pkt.len = (lastChunkSize);
memcpy(pkt.data, fileContent.data() + fileSize / chunkSize * chunkSize, lastChunkSize);
pkt.chsum = 0;
pkt.finished = 1;
ssize_t b = sendto(newSock, &pkt, pkt.len, 0, &clntAddr, clntAddrLen);
if(b == lastChunkSize)
cout << "Success size" << endl;
ack_packet receivedPacket;
recvfrom(newSock, (void*)&receivedPacket, 2, MSG_WAITALL, &clntAddr, &clntAddrLen);
cout << "Acknowledged message " << receivedPacket.ackno << endl;
}
这是客户端感兴趣的代码:
int s = 0;
struct sockaddr temp{};
socklen_t sz;
uint16_t waiting_for_package_x = 0;
while(true){
packet receivedPacket{};
numBytes = recvfrom(sock, (void*)&receivedPacket, 508, MSG_WAITALL,
&temp, &sz);
s+=numBytes-8;
if (numBytes < 0)
DieWithSystemMessage("recvfrom() failed");
if(receivedPacket.seqno != waiting_for_package_x){
cout << receivedPacket.seqno << " " << waiting_for_package_x << endl;
exit(-1);
}
waiting_for_package_x++;
outputFile.write(receivedPacket.data, receivedPacket.len-8);
ack_packet ackPacket{};
ackPacket.chsum= (0);
ackPacket.ackno= (receivedPacket.seqno);
ackPacket.len = (6);
sendto(sock, &ackPacket, 6,
0, &temp, sz);
if(receivedPacket.finished == 1)
break;
}
s
是告诉我客户端收到了多少字节的变量。
我怀疑
ofstream
中的写入函数忽略了某些写入操作,可能是因为它有某种内部缓冲区,在某些接收期间已被填充。不过我觉得这样是不对的。
问题是我没有关闭文件。一旦关闭,数据就被正确写入。 感谢主,这就是问题所在