Reputation: 43
I wrote a simple tcp/ip
connection client-server
in c++
.
This is the part of the server that handles the connection
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;
}
but this works if I know the total amount of bytes to be read. What if the total amount of data to be read is unknown? How I can modify this piece of code?
Upvotes: 1
Views: 4260
Reputation: 182761
You asked how to fix your low-level receiving code. That's simple -- just call read
once and don't use a while
loop. The call to read
will return as soon as at least one byte of data can be read. For the number of bytes to read, just pass in the size of your buffer (or the space left in it if there's already some leftover in it from a prior call).
You will also need high-level protocol code, just as you do if you know the number of bytes. That code will probably need to be a bit different. If the chunk of bytes you got includes your stop indication, then process all the bytes up to the stop indication and keep the extra in the buffer for next time. If not, just call read
again and get a bunch more bytes.
Your protocol handling code should look sort of like this:
read
and add however many bytes you got to the buffer. (Handle an error or normal close here.)Also, the code you gave in the question will spin forever if the other side closes the connection. In this case, read
will return zero and you will never be able to read any more data from the connection. You should break out of the loop if read
returns zero.
Upvotes: 3
Reputation: 62563
First of all, get rid of all bzero
calls. I do not know why this keeps creeping into good people's code. There is zero, nada, nicht need for this.
Second of all, you'd need to either somehow communicate the size of transmission beforehand - for example, HTTP 1.1 provides for this information in the header - or simply state that connection is closed once all the data has been transferred - this would be HTTP 1.0 model.
Upvotes: 2