我实现了一个从一个套接字接收并从另一个套接字发送/接收的程序。
为此我使用select()的轮询,在套接字1中,我以高数据速率接收数据,而在另一个套接字中,我接收定期消息并请求从第一个套接字接收数据。
当没有“来自套接字2”的请求将数据从套接字1委托给socket2时,我从套接字1正常接收数据并且没有问题。但是,假设我收到两个请求“套接字2”而数据正在套接字1中接收,第二个请求打破了数据接收,好像它再也无法跟上速率“速率不高真的只有150赫兹” 。
我在main()中做的伪代码:
fd_set readfds, rd_fds, writefds, wr_fds;
struct timeval tv;
do
{
do
{
rd_fds = readfds;
wr_fds = writefds;
FD_ZERO (&rd_fds);
FD_SET (sock1, &rd_fds);
FD_SET (sock2, &rd_fds);
FD_SET (sock1, &wr_fds);
tv.tv_sec = 0;
tv.tv_usec = 20;
int ls = sock2 + 1;
rslt = select (ls, &rd_fds, &wr_fds, NULL, &tv);
}
while (rslt == -1 && errno == EINTR);
if (FD_ISSET (sock1, &rd_fds))
{
rs1 = recvfrom (sock1, buff, size of the buff, ....);
if (rs1 > 0)
{
if (rs1 = alive message)
{
/* system is alive; */
}
else if (rs1 == request message)
{
/* store Request info (list or vector) */
}
else {}
}
}
if (FD_ISSET (StructArg.sock2, &rd_fds))
{
rs2 = recv (sock2, ..., 0);
if (rs2 > 0)
{
if ( /* Message (high rate) is from sock 2 */ )
{
/* process this message and do some computation */
int sp1 = sendto (sock1, .....);
if (sp1 < 0)
{
perror ("Failed data transmission ");
}
else
{
/* increase some counters */
}
}
}
}
if (FD_ISSET (sock1, &wr_fds))
{
/*
if there info stored in the list
do some calculaitons then send to sock 1
*/
if (sendto (sock1, ... ...) < 0)
{
perror ("Failed data transmission");
}
else
{
/* increase counter */
}
}
FD_CLR (sock1, &rd_fds);
FD_CLR (sock2, &rd_fds);
}
while (1);
同样,问题是,如果从sock2收到请求,为什么从sock1接收中断,而我从sock1(快速消息)接收,我期望输出中的交错消息基于消息中的时间戳。
答案 0 :(得分:0)
请注意,除非您使用O_NONBLOCK选项创建套接字,否则几乎所有套接字函数都可以阻止执行:
http://pubs.opengroup.org/onlinepubs/009695399/functions/sendto.html
除非你使用MSG_WAITALL,否则你还必须处理recvfrom只给你部分读取的情况:
http://pubs.opengroup.org/onlinepubs/009695399/functions/recvfrom.html
就个人而言,我使用多线程实现,它可以让线程坐下来等待每个套接字上的数据。
关于你的最后一个问题:
为什么从sock2收到请求时sock1的接收被中断,而我从sock1(快速消息)收到请求时,我希望输出中的交错消息基于消息中的时间戳。
您是网络堆栈实现的奴隶,几乎不保证在一个套接字上相对于另一个套接字发送或接收数据。您只能保证套接字中的数据正确排序。
答案 1 :(得分:0)
我希望输出中的交错消息基于消息中的时间戳。
你的期望没有基础。如果任一套接字缓冲区中都有数据,select()
将触发。这就是你可以信赖的全部。您无法保证在多个套接字之间观察和订购时间戳。