客户端写入字节数少于预期

问题描述 投票:0回答:1

我正在尝试使用 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
中的写入函数忽略了某些写入操作,可能是因为它有某种内部缓冲区,在某些接收期间已被填充。不过我觉得这样是不对的。

c++ file sockets stream
1个回答
0
投票

问题是我没有关闭文件。一旦关闭,数据就被正确写入。 感谢主,这就是问题所在

© www.soinside.com 2019 - 2024. All rights reserved.