2011-12-27 16 views
1

更新: 我添加了一个while以获取剩余数据,解决了问题。谢谢你们。我通过套接字发送C结构,但无法正确地完成,总是会丢失一些字节

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; 
} 

我想通过socket发送结构mfsiowrite返回值是37772,但是当我从其他程序得到它的read返回值是32768,这是非常奇怪的。

这种结构的定义在这里

struct mfsio{ 
    size_t size; 
    char buf[]; 
}; 

的发送代码是在这里

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); 

接收代码是在这里

struct mfsio *rcvread; 
rcvread = malloc(sizeof(struct mfsio) + size); 
res = 0;  
res = read(connfd, rcvread, sizeof(struct mfsio) + size); 

size等于rcvcmd->size和RES pread是32678,水库write是32772. 但read的资源是32678.

这种情况怎么会发生?我在这里做错了什么?

如果没有来自write输入时,read功能只是在等待一些数据,只是挂在那里

如果我使用一个循环来避免这样的问题,我怎么能最终得到了整个数据结构,我的意思是如果我循环读取,我会从套接字中获取剩余的字节,但我怎样才能将这些剪辑合并到一起?

+0

您必须将您读入的指针调整为循环的一部分,并在其中添加之前读取的字节数。确保你使用这个指针算术的字符指针。 – 2011-12-27 14:14:50

+1

结构填充不可移植。您需要发送数据的序列化表示。 – u0b34a0f6ae 2011-12-27 19:06:24

+0

@ kaizer.se那么,有没有在Linux上的任何lib可以做到这一点?我做了一些谷歌搜索,但没有找到。 – bxshi 2011-12-28 08:40:56

回答

8

您需要在循环中进行读写操作,直到读取/写入所有预期数据。对于阅读,你必须阅读,直到它返回0,表示没有其他可用。或-1表示错误。

你最近的问题是,你正在使用指针运算与结构指针:

tmp = recv(connfd, rcvread + res, rcvread->size + 4 - res, 0); 

在C,当你做你不与字节的工作指针算法,但你用的大小工作对象(例如rvcread)。您应该定义一个char *,它是您读取位置的字节位置,然后在读取数据时更新此位置。

+0

我想得到这个结构。如果我使用循环,那么我只能得到左边的字节,而不是整个结构。有没有办法解决这个问题? – bxshi 2011-12-27 14:04:17

+1

我想你最好通过loop语句接收所有数据,就像上面的Upton的答案一样。 – 2011-12-27 14:07:49

+0

我添加了这些代码来获取剩余数据,但它返回了一个“错误的地址”。 \t tmp = recv(connfd,(void *)(rcvread + res),rcvread-> size + 4 - res(012) ,0); \t \t如果(TMP == -1) \t \t \t的printf( “错误:%s \ n” 个,(字符*)字符串错误(错误)); \t \t res + = tmp; \t}' – bxshi 2011-12-27 15:37:33

0

readwrite对字节流进行操作。没有保证读取会读写写入它的字节数量。使用sendmsg或将记录大小或记录分隔符放入流中。

0

弗朗西斯厄普顿的答案似乎是正确的,你应该遵循他的建议。
但我有另一个猜测,也许这是问题。
您不会显示如何在接收器中获得大小的值。一个合理的方法是从套接字读取4个字节大小。所以如果你这样做了,你已经读了4个字节,并且在下一次读取时会减少4个字节。

+0

我刚刚从我的接收器中读取了最大可能的字节大小,并且数据等于或小于那个大小。 – bxshi 2011-12-27 14:34:54

+0

@bxshi:这个概念不起作用。发送者需要提供写入的_actual_大小,否则您无法在读者端确定要读取的字节数。 – 2011-12-27 14:38:58

0

recv()标志MSG_WAITALL也可能会感兴趣,因为它基本上整个

while (!allDataReceived) { 
    receiveMoreData(); 
} 

东西给你。

但是,其他答案暗示你应该发送一个标题为“这是多少字节将遵循”,这绝对是你应该听的东西。

相关问题