[英]C socket programming: calling recv() changes my socket file descriptor?
Hey all, I have this strange problem with recv(). 嘿所有,我有recv()这个奇怪的问题。 I'm programming client/server where client send() a message (a structure to be exact) and server recv() it.
我正在编程客户端/服务器,其中客户端发送()消息(结构准确)和服务器recv()它。 I am also working with multiple sockets and select().
我也在使用多个套接字和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. 我
read_set
的问题是在read_set
,0~3没有设置,4是。 That is fine. 那样就好。 But when i call
recv()
, i
suddently becomes 0. Why is that? 但是当我打电话给
recv()
, i
突然变成了0.为什么会这样? It doesn't make sense to me why recv()
would take an socket file descriptor number and modify to another number. 对我来说,为什么
recv()
会获取套接字文件描述符号并修改为另一个数字是没有意义的。 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. 这就是打印出来的东西。
recv
cannot modify its first argument, since it is taken by value. recv
无法修改其第一个参数,因为它是按值获取的。
You don't show where you've declared msg
or i
, but based on this line 您没有显示您声明
msg
或i
,但是基于此行
printf("S: msg says %s\n", msg->_payload);
Where you use the ->
operator on msg
, I assume it's probably like this: 在
msg
上使用->
运算符的地方,我假设它可能是这样的:
struct somestruct* msg = malloc(sizeof(struct somestruct));
int i;
Then you do this: 然后你这样做:
num_bytes = recv(i, &msg, MAX_MSG_BYTE, 0);
Note that msg
is already a pointer, so &msg
is a pointer to the pointer . 请注意,
msg
已经是指针,因此&msg
是指向指针的指针 。
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 that msg
points to . 那么这将完成是接收数据,并试图将其存储在地方,
msg
指针本身,而不是地方, msg
点 。 Typically, pointers are only 4 bytes long, so this will overflow the storage if you receive more than four bytes. 通常,指针只有4个字节长,因此如果您收到的字节数超过4个,这将溢出存储空间。 If
i
is declared on the stack after msg
, 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. 如果在
msg
之后在堆栈上声明了i
,则很可能它被此溢出覆盖,并且它恰好被接收到的数据包中的所有零字节覆盖。
Since msg
is already a pointer, change your receive line to eliminate the superfluous indirection: 由于
msg
已经是指针,因此请更改接收行以消除多余的间接:
num_bytes = recv(i, msg, MAX_MSG_BYTE, 0);
Similarly, you may want to consider making the same change to the line 同样,您可能需要考虑对该行进行相同的更改
handle_request(arg, &msg)
if the handle_request
function is not really expecting a pointer-to-pointer. 如果
handle_request
函数实际上并不期望指向指针。
我的第一个猜测是sizeof(msg) < MAX_MSG_BYTE
,当recv
溢出msg
它会破坏i
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.