c ++从套接字

时间:2015-12-30 20:59:48

标签: c++ sockets tcp bytestream

我在tcp/ip中写了一个简单的client-server连接c++

这是处理连接的服务器的一部分

int sockfd, newsockfd;
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
int n = 0;

sockfd = socket(AF_INET,SOCK_STREAM,0);
if(sockfd < 0){
    cout << "Error opening socket" << endl;
    exit(1);
}

bzero((char*)&serv_addr, sizeof(serv_addr));

serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);

if(bind(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr))<0){
    cout << "Error binding" << endl;
    exit(1);
}

listen(sockfd,1);
clilen = sizeof(cli_addr);

newsockfd = accept(sockfd,(struct  sockaddr *)&cli_addr, &clilen );

if(newsockfd < 0){
    cout << "Error accepting" << endl;
    exit(1);
}

bzero(bytes,size_tot);
uint64_t total_bytes_read = 0;
uint64_t total_bytes_to_read = size_tot;
while(total_bytes_read < total_bytes_to_read){
    int bytes_read = read(newsockfd,bytes + total_bytes_read,total_bytes_to_read - total_bytes_read);
    if(bytes_read == -1){
        cout << "error reading "<< endl;
        n = -1;
        break;
    }
    total_bytes_read += bytes_read;
}

但如果我知道要读取的总字节数,这是有效的。如果要读取的数据总量未知,该怎么办?我如何修改这段代码?

2 个答案:

答案 0 :(得分:3)

您询问了如何修复低级接收代码。这很简单 - 只需调用read一次,不要使用while循环。只要可以读取至少一个字节的数据,就会返回对read的调用。对于要读取的字节数,只需传入缓冲区的大小(如果先前的调用中已经有一些剩余的空间,则传入其中的空间)。

您还需要高级协议代码,就像您知道字节数一样。该代码可能需要有点不同。如果您获得的字节块包括停止指示,则将所有字节处理为停止指示,并将额外的数据保留在缓冲区中以供下次使用。如果没有,只需再次调用read并获得更多字节。

你的协议处理代码看起来应该是这样的:

  1. 调用read并添加许多字节到缓冲区。 (在此处理错误或正常关闭。)
  2. 如果缓冲区中的数据不包含停止指示,请转到步骤1.
  3. 处理所有字节,直至停止指示。
  4. 从缓冲区中删除已处理的字节,留下任何未处理的字节。
  5. 转到第2步。
  6. 此外,如果对方关闭连接,您在问题中提供的代码将永远旋转。在这种情况下,read将返回零,您将永远无法从连接中读取任何更多数据。如果read返回零,你应该突破循环。

答案 1 :(得分:2)

首先,摆脱所有bzero次电话。我不知道为什么这会一直蔓延到好人的代码中。没有,nada,nicht需要这个。

其次,您需要预先以某种方式传达传输的大小 - 例如,HTTP 1.1在标头中提供此信息 - 或者只是说明一旦所有数据都已传输,连接就会关闭 - 这将是HTTP 1.0模型。