在插座上选择与数据混淆

时间:2012-01-16 17:25:04

标签: c++ sockets select recv

我正在通过套接字发送一些数据,但我需要设置超时 我正在使用类似的东西:

fd_set rfds;
struct timeval tv;
int retval;
/* Watch stdin (fd 0) to see when it has input. */
FD_ZERO(&rfds);
FD_SET(sockDesc, &rfds);
/* Wait up to five seconds. */
tv.tv_sec = 5;
tv.tv_usec = 0;
retval = select(sockDesc + 1, &rfds, NULL, NULL, &tv);
if(rtn = ::recv(sockDesc, (raw_type*) buffer, bufferLen, 0)) < 0){
throw SocketException("error", true);
}
return rtn;

因此。
根据我返回的数据类型,我需要实现超时 如果我只是发送文本数据我不需要,如果我发送一个文件,我需要...
为了解释或多或少,我通过套接字发送一些数据并在另一侧进行处理 所以,如果我发送一个tar:

while(readtar){

  senddata
  get processed data
}

但有时发送的数据只是标题,所以当另一方处理数据时,它不需要返回数据,套接字在读取时停止。
为了显示:     cat file.tar | myprogram -c“tar -zvt”

因此,在收到足够的数据返回文件名之前,它不会返回任何内容。

如果我只是发送一个文件并返回“猫”我没有这个问题 echo“asjdoiajdlaijdkasdjlkas”| myprogram -c“cat”

猫HUGEFILE.tar | myprogram -c“cat”| tar -zvt
在这种情况下,它做同样的事情,但不在服务器端......所以它对我不起作用。

现在....如果我只是在没有选择的情况下使用recv,当我使用它返回数据时,它可以工作......没有问题。
但如果我实施选择,数据就会搞砸了。

没有选择

send "command line text temp test"
recv "command line text temp test"

使用

send "command line text temp test"
recv "commmand lin/ˆ
1k5d99ck"

只是为了说明正在发生的事情

客户端循环:

while(size = read(fileno(stdin), thebuffer, 10000)){
  sock->send(thebuffer, size); // if this data is not enough the other side never sends the data back
  sock->recv //receive data
}

另一方面我做了

if(pid == 0){
//stuffs closes, dup2
execlp("bash", "bash", "-c", "run.c_str(), NULL); // if i use one tar -zvt i need a bunch of data to generate the return
  }
else
while(size = read(fout[0], buffer, 10000) > 0)){
  sock->send(buffer, size);
}

所以..如果发送的数据不足以生成on 如果我可以检查读取是否有任何内容,或者如果execlp发送终结符,则可以在stdin端检查问题

1 个答案:

答案 0 :(得分:4)

听起来你期望你的TCP recv()以特定大小的块返回数据...但是,TCP recv()不会那样工作。 TCP是基于流的,因此recv()返回的字节数可能在1(或0,如果你使用非阻塞I / O)和你传入的缓冲区大小之间的任何地方变化。然后由你决定接收代码以根据需要循环以再次重新连接接收的数据。

此外,您似乎正在尝试打印出未终止的ASCII字符串 - 这将解释第二个recv()示例末尾的垃圾字符。 (即,如果要将接收到的数据字节打印为字符串,请确保在最后一个接收到的字节后放置一个NUL / 0字节; recv()将不会为您执行此操作)

相关问题