在套接字上选择会弄乱数据
我正在通过套接字发送一些数据,但我需要设置超时。
我正在使用类似的东西:
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
}
但有时发送的数据只是标头,因此当另一端处理数据时,它不需要返回数据,并且套接字在读取时停止。
举例说明: 猫文件.tar | myprogram -c "tar -zvt"
因此,在收到足够的数据来返回文件名之前,它不会返回任何内容。
如果我只发送一个文件并返回“cat”,我就不会遇到此问题
回声“asjdoiajdlaijdkasdjlkas”| myprogram -c“猫”
或
猫巨大文件.tar | myprogram -c“猫”| tar -zvt
在这种情况下,它做同样的事情,但不在服务器端......所以它对我不起作用。
现在......如果我在使用返回数据时只使用recv而不使用select猫 它有效...没有问题。
但是如果我实现选择,数据就会变得混乱。
没有选择
send "command line text temp test"
recv "command line text temp test"
WI
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);
}
这样做..如果发送的数据不足以生成 如果我可以检查 read 是否有任何内容,或者在 stdin 端,如果 execlp 发送终止符,我可以解决问题
I'm sending some data trough the socket, but I need to set the timeout.
I'm using something like:
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;
So.
Depending the type of data I return I need to implement timeout or not.
If I just send text data I don't need, if I send one file I need...
To explain more or less I'm sending some data through a socket and processing on the other side.
So, if I send one tar:
while(readtar){
senddata
get processed data
}
but sometimes the data sent is just the header, so when the other side process data it doesn't needs to return data and the socket stops on read.
To illustrate:
cat file.tar | myprogram -c "tar -zvt"
So it don't return nothing until receive enough data to return the name of file.
If i just send one file and returns the "cat" i dont have this problem
echo "asjdoiajdlaijdkasdjlkas" | myprogram -c "cat"
or
cat HUGEFILE.tar | myprogram -c "cat" | tar -zvt
In this case it does the same thing, but is not on the server side... so it dont work for me.
Now.... If I just use the recv without the select when I return the data using the cat it works... no problems with that.
BUT if I implement the select the data comes messed up.
WITHOUT SELECT
send "command line text temp test"
recv "command line text temp test"
WITH
send "command line text temp test"
recv "commmand lin/ˆ
1k5d99ck"
it's just to illustrate what is happening
Client loop:
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
}
On the other side I do
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);
}
So.. if the data sent is not enough to generate on
If I could check if read have anything or on the stdin side if the execlp send a terminator I could solve the problem
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
听起来您希望 TCP recv() 以特定大小的块向您返回数据...但是,TCP recv() 并不是这样工作的。 TCP 是基于流的,因此 recv() 返回的字节数可能在 1(如果使用非阻塞 I/O,则为 0)和传入的缓冲区大小之间的任意位置变化。然后由您决定接收代码根据需要循环以再次重新连接接收到的数据。
另外,您似乎正在尝试打印出未终止的 ASCII 字符串——这将解释第二个 recv() 示例末尾的垃圾字符。 (即,如果您想将接收到的数据字节作为字符串打印出来,请务必在最后接收到的字节后面放置一个 NUL/0 字节;recv() 不会为您执行此操作)
It sounds like you are expecting your TCP recv() to return data to you in chunks of a particular size... however, TCP recv() does not work that way. TCP is stream-based, so the number of bytes returned by recv() may vary anywhere between 1 (or 0 if you are using non-blocking I/O) and the size of the buffer you passed in. It's then up to your receiving code to loop as necessary to re-concatenate the received data again.
Also, it looks like you are trying to print out un-terminated ASCII strings -- that would explain the garbage characters at the end of your second recv() example. (i.e. if you want to print out the received data bytes as a string, be sure to place a NUL/0 byte after the last received byte; recv() won't do that for you)