Reputation: 2292
Update:
I add a while
to get the remain data, problem solved. thanks you guys.
while(res != rcvread->size + 4) {/* do not get full data */
tmp = recv(connfd, (void *)rcvread + res, rcvread->size + 4 - res, 0);
if(tmp == -1)
printf("error:%s\n",(char *)strerror(errno));
res+=tmp;
}
I want to send a structure mfsio
through socket, the return value of write
is 37772, but when I got it from the other program, the return value of read
is 32768, that's really odd.
The definition of this structure is here
struct mfsio{
size_t size;
char buf[];
};
The send code is here
struct mfsio *sndread;
sndread = malloc(sizeof(struct mfsio) + rcvcmd->size);
res = pread(fd, &(sndread->buf), rcvcmd->size, rcvcmd->offset);
sndread->size = res;
res = write(connfd, sndread, sizeof(struct mfsio) + res);
The receive code is here
struct mfsio *rcvread;
rcvread = malloc(sizeof(struct mfsio) + size);
res = 0;
res = read(connfd, rcvread, sizeof(struct mfsio) + size);
size
equals to rcvcmd->size
, and the res of pread
is 32678, the res of write
is 32772.
but res of read
is 32678.
How can such thing happened? Does I do something wrong here?
If there is no input from write
, the read
function will just waiting for some data and just hanging there
If I use a loop to avoid such problem, how can I finally get the entire data structure, I mean if I do loop reading, I will get the remain bytes from the socket, but how can I combine these clips I get?
Upvotes: 1
Views: 1316
Reputation: 1
The flag MSG_WAITALL
on recv()
might also be of interest, as it basically does the whole
while (!allDataReceived) {
receiveMoreData();
}
thing for you.
However, the other answers hinting you that you should send a header with "this is how many bytes will follow" are definitely something you should listen to as well.
Upvotes: 0
Reputation: 19443
You need to do your reads and writes in a loop until all of the expected data is read/written. For the read, you have to read until it returns 0, indicating nothing else is available. Or -1 indicating an error.
Your more recent problem is that you are using pointer arithmetic with your struct pointer:
tmp = recv(connfd, rcvread + res, rcvread->size + 4 - res, 0);
In C when you do pointer arithmetic you are not working with bytes, but you are working with the size of the object (rvcread for example). You should define a char *
which is the byte location of where you will read into and then update this as you read through the data.
Upvotes: 8
Reputation: 16441
Francis Upton's answer seems like the right one, you should certainly follow his advice.
But I have another guess, maybe it's the problem.
You don't show how you get the value of size in the receiver. A reasonable way to do it would be to read 4 bytes from the socket into size. So if you did that, you already read 4 bytes, and will get 4 bytes less in the next read.
Upvotes: 0
Reputation: 151
read
and write
operate on byte streams. There is no guaranty that read will read as many bytes as write wrote to it. Either use sendmsg or put record sizes or record separators into the stream.
Upvotes: 0