程序使用单个UDP套接字和sendto()
与4个微控制器设备通信。主程序循环的每次迭代都调用sendto()
函数,以更新程序状态的控制器。
如果我只发送到1个设备是可以的。但是,如果我尝试发送到4个设备,我会非常频繁地得到EAGAIN
错误,以至于无法通信。
我怎样才能消除这些错误呢?我不能阻塞套接字,因为这会降低整个程序的速度,因为它需要几乎在瞬间处理许多其他函数。
我可以不那么频繁地发送sendto()
消息,但我仍然希望每秒向每个设备发送2-3条300字节的消息。
如果我使用select()
,则会有一个额外的问题,即确保每个设备获得相同的套接字份额。
main_loop {
open_chamber_socket();
while (!sig_received) {
unsigned char * buf;
for (keydata_poll = 0; msgsize < 0 && errno == ENOMSG && !must_term; keydata_poll++) {
if ((keydata_poll % 12) == 0) {
deferred_activities();
}
msgsize = msgrcv (msgqid
, (struct msgbuf_s *)msg, MSGTEXTSIZE (msg)
, MSGID_KEYDATA, IPC_NOWAIT);
if (msgsize >= 0)
break;
usleep(500);
}
if (msgsize < 0) {
if (errno != EINTR) { // report any error except a termination signal
log_perror(MYNAME ": Error receiving queued message.");
usleep(5 * 1000);
}
continue;
}
switch (msg->mtext.action) {
...
}
...
}
}
deferred_activities() {
...
two thousand lines of code which bit by bit build the send buffers
...
int j, code;
for (j=0; j<4; j++) {
struct sockaddr_in addr = {.sin_family = AF_INET, .sin_port = htons(4096)};
addr.sin_addr.s_addr = device[j]->net_address;
addr.sin_port = device[j]->net_port;
code = sendto(e_socket, device[j]->buf, device[j]->datasize, 0, (struct sockaddr *) &addr, sizeof addr);
}
}
int open_chamber_socket(void)
{
int code, flags;
struct sockaddr_in addr;
int optval = 1;
e_socket = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (e_socket < 0) {
log_perror (_("%s: Can't create chamber socket."), MYNAME);
return e_socket;
}
// set non-blocking flag on the socket ..
flags = fcntl (e_socket, F_GETFL, 0);
if (flags != -1)
fcntl (e_socket, F_SETFL, flags | O_NONBLOCK);
setsockopt(e_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
bzero((char *) &addr, sizeof addr);
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl (CHAMBER_ADDRESS);
addr.sin_port = htons (CHAMBER_PORT);
code = bind (e_socket, (struct sockaddr *)&addr, sizeof addr);
if (code < 0) {
log_perror (_("%s: Can't bind chamber socket to 10.0.0.1:%d."), MYNAME, CHAMBER_PORT);
return code;
}
return 0;
}
系统:Debian Linux靶心
1条答案
按热度按时间kmpatx3s1#
增加Linux操作系统UDP缓冲区可以解决这个冲突。在/etc/sysctl.conf中,我将读写缓冲区都设置为默认值1 MB和最大值25 MB: