C 套接字编程:调用 recv() 会更改我的套接字文件描述符吗?
大家好,我在使用recv()时遇到了这个奇怪的问题。我正在对客户端/服务器进行编程,其中客户端 send() 一条消息(确切地说是一个结构),服务器 receive() 消息。我还使用多个套接字和 select()。
while(1)
{
readset = info->read_set;
info->copy_set = info->read_set;
timeout.tv_sec = 1;
timeout.tv_usec = 0; // 0.5 seconds
ready = select(info->max_fd+1, &readset, NULL, NULL, &timeout);
if (ready == -1)
{
printf("S: ERROR: select(): %s\nEXITING...", strerror(errno));
exit(1);
}
else if (ready == 0)
{
continue;
}
else
{
printf("S: oh finally you have contacted me!\n");
for(i = 0; i < (info->max_fd+1); i++)
{
if(FD_ISSET(i, &readset)) //this is where problem begins
{
printf("S: %i is set\n", i);
printf("S: we talking about socket %i son\n", i); // i = 4
num_bytes = recv(i, &msg, MAX_MSG_BYTE, 0);
printf("S: number of bytes recieved in socket %i is %i\n", i, num_bytes); // prints out i = 0 what??
if (num_bytes == 0)
{
printf("S: socket has been closed\n");
break;
}
else if (num_bytes == -1)
{
printf("S: ERROR recv: %d %s \n", i, strerror(errno));
continue;
}
else
{
handle_request(arg, &msg);
printf("S: msg says %s\n", msg->_payload);
}
} // if (FD_ISSET(i, &readset)
else
printf("S: %i is not set\n", i);
} // for (i = 0; i < maxfd+1; i++) to check sockets for msg
} // if (ready == -1)
info->read_set = info->copy_set;
printf("S: copied\n");
}
我遇到的问题是在read_set
中,0~3没有设置,而4是。那很好。但是当我调用recv()
时,i
突然变成0。这是为什么呢?对我来说,为什么 recv()
会采用套接字文件描述符编号并修改为另一个编号,这对我来说没有意义。这正常吗?我错过了什么吗?
S: 0 is not set
S: 1 is not set
S: 2 is not set
S: 3 is not set
S: 4 is set
S: we talking about socket 4 son
S: i is strangely or unstrangely 0
S: number of bytes recieved in socket 0 is 40
这就是它打印出来的内容。
Hey all, I have this strange problem with recv(). I'm programming client/server where client send() a message (a structure to be exact) and server recv() it. I am also working with multiple sockets and select().
while(1)
{
readset = info->read_set;
info->copy_set = info->read_set;
timeout.tv_sec = 1;
timeout.tv_usec = 0; // 0.5 seconds
ready = select(info->max_fd+1, &readset, NULL, NULL, &timeout);
if (ready == -1)
{
printf("S: ERROR: select(): %s\nEXITING...", strerror(errno));
exit(1);
}
else if (ready == 0)
{
continue;
}
else
{
printf("S: oh finally you have contacted me!\n");
for(i = 0; i < (info->max_fd+1); i++)
{
if(FD_ISSET(i, &readset)) //this is where problem begins
{
printf("S: %i is set\n", i);
printf("S: we talking about socket %i son\n", i); // i = 4
num_bytes = recv(i, &msg, MAX_MSG_BYTE, 0);
printf("S: number of bytes recieved in socket %i is %i\n", i, num_bytes); // prints out i = 0 what??
if (num_bytes == 0)
{
printf("S: socket has been closed\n");
break;
}
else if (num_bytes == -1)
{
printf("S: ERROR recv: %d %s \n", i, strerror(errno));
continue;
}
else
{
handle_request(arg, &msg);
printf("S: msg says %s\n", msg->_payload);
}
} // if (FD_ISSET(i, &readset)
else
printf("S: %i is not set\n", i);
} // for (i = 0; i < maxfd+1; i++) to check sockets for msg
} // if (ready == -1)
info->read_set = info->copy_set;
printf("S: copied\n");
}
the problem I have is that in read_set
, 0~3 aren't set and 4 is. That is fine. But when i call recv()
, i
suddently becomes 0. Why is that? It doesn't make sense to me why recv()
would take an socket file descriptor number and modify to another number. Is that normal? Am I missing something?
S: 0 is not set
S: 1 is not set
S: 2 is not set
S: 3 is not set
S: 4 is set
S: we talking about socket 4 son
S: i is strangely or unstrangely 0
S: number of bytes recieved in socket 0 is 40
That's what it prints out.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
recv
无法修改其第一个参数,因为它是按值获取的。您不会显示声明
msg
或i
的位置,而是基于此行在< 上使用
->
运算符的位置code>msg,我假设它可能是这样的:然后你这样做:
注意
msg
已经是一个指针,所以&msg< /code> 是指向指针的指针。
接下来要做的就是接收数据并尝试将其存储在
msg
pointer 本身所在的位置,而不是msg
指向的位置到。通常,指针只有 4 个字节长,因此如果接收超过 4 个字节,就会导致存储溢出。如果i
在msg
之后在堆栈上声明,那么它很可能被此溢出覆盖,并且它恰好被接收到的所有零字节覆盖包。由于
msg
已经是一个指针,因此更改您的接收行以消除多余的间接:您可能需要考虑对该行进行相同的更改
同样,如果
handle_request
函数是, 并不真正期待指针到指针。recv
cannot modify its first argument, since it is taken by value.You don't show where you've declared
msg
ori
, but based on this lineWhere you use the
->
operator onmsg
, I assume it's probably like this:Then you do this:
Note that
msg
is already a pointer, so&msg
is a pointer to the pointer.What this will then do is receive data and try to store it in the place where the
msg
pointer itself is, not the place thatmsg
points to. Typically, pointers are only 4 bytes long, so this will overflow the storage if you receive more than four bytes. Ifi
is declared on the stack aftermsg
, then it is likely that it is being overwritten by this overflow, and it happens to get overwritten by all zero bytes from the received packet.Since
msg
is already a pointer, change your receive line to eliminate the superfluous indirection:Similarly, you may want to consider making the same change to the line
if the
handle_request
function is not really expecting a pointer-to-pointer.我的第一个猜测是 sizeof(msg)
sizeof(msg)
sizeof(msg)
sizeof(msg) < MAX_MSG_BYTE
并且当recv
溢出msg
时,它会丢弃i
。My first guess would be that
sizeof(msg) < MAX_MSG_BYTE
and whenrecv
overflowsmsg
it trashesi
.