PDA

View Full Version : [C] Gestione connessione tramite socket


lordjoseph
24-02-2012, 21:35
Ciao a tutti,

ho iniziato da poco ad usare i socket e avrei un problema da risolvere.
Ho un programma che usa i socket per poter ricevere messaggi da un'interfaccia di rete, quando però questa va giù (network down) il programma dovrebbe ritentare la connessione e quindi rimanere in ascolto fin quando la rete non torni up.
Qual è il metodo corretto per far quanto richiesto?
Chiudo i socket e li riapro ogni tot secondi o c'è un'istruzione da ripetere semplicemente per rimanere in ascolto (basta ciclare sulla select e sulla recvmsg?)



if (ioctl(s[i], SIOCGIFINDEX, &ifr) < 0) {
perror("SIOCGIFINDEX");
exit(1);
}
addr.can_ifindex = ifr.ifr_ifindex;

numfilter = 0;
rfilter = malloc(sizeof(struct can_filter) * nID);
..........
..........
setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_FILTER,
rfilter, numfilter * sizeof(struct can_filter));

free(rfilter);



if (rcvbuf_size) {

int curr_rcvbuf_size;
socklen_t curr_rcvbuf_size_len = sizeof(curr_rcvbuf_size);

/* try SO_RCVBUFFORCE first, if we run with CAP_NET_ADMIN */
if (setsockopt(s[i], SOL_SOCKET, SO_RCVBUFFORCE,
&rcvbuf_size, sizeof(rcvbuf_size)) < 0) {
#ifdef DEBUG
printf("SO_RCVBUFFORCE failed so try SO_RCVBUF ...\n");
#endif
if (setsockopt(s[i], SOL_SOCKET, SO_RCVBUF,
&rcvbuf_size, sizeof(rcvbuf_size)) < 0) {
perror("setsockopt SO_RCVBUF");
return 1;
}

if (getsockopt(s[i], SOL_SOCKET, SO_RCVBUF,
&curr_rcvbuf_size, &curr_rcvbuf_size_len) < 0) {
perror("getsockopt SO_RCVBUF");
return 1;
}

/* Only print a warning the first time we detect the adjustment */
/* n.b.: The wanted size is doubled in Linux in net/sore/sock.c */
if (!i && curr_rcvbuf_size < rcvbuf_size*2)
fprintf(stderr, "The socket receive buffer size was"
"adjusted due to /proc/sys/net/core/rmem_max.\n");
}
}

if (timestamp || log || logfrmt) {

const int timestamp_on = 1;

if (setsockopt(s[i], SOL_SOCKET, SO_TIMESTAMP,
&timestamp_on, sizeof(timestamp_on)) < 0) {
perror("setsockopt SO_TIMESTAMP");
return 1;
}
}

if (dropmonitor) {

const int dropmonitor_on = 1;

if (setsockopt(s[i], SOL_SOCKET, SO_RXQ_OVFL,
&dropmonitor_on, sizeof(dropmonitor_on)) < 0) {
perror("setsockopt SO_RXQ_OVFL not supported by your Linux Kernel");
return 1;
}
}

if (bind(s[i], (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("bind");
return 1;
}
}



/* these settings are static and can be held out of the hot path */
iov.iov_base = &frame;
msg.msg_name = &addr;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = &ctrlmsg;

while (running) {

FD_ZERO(&rdfs);
for (i=0; i<currmax; i++)
FD_SET(s[i], &rdfs);

if ((ret = select(s[currmax-1]+1, &rdfs, NULL, NULL, NULL)) < 0) {
//perror("select");
running = 0;
continue;
}

for (i=0; i<currmax; i++) { /* check all CAN RAW sockets */

if (FD_ISSET(s[i], &rdfs)) {

int idx;

/* these settings may be modified by recvmsg() */
iov.iov_len = sizeof(frame);
msg.msg_namelen = sizeof(addr);
msg.msg_controllen = sizeof(ctrlmsg);
msg.msg_flags = 0;

nbytes = recvmsg(s[i], &msg, 0);
if (nbytes < 0) {
perror("read");
return 1;
}

lordjoseph
25-02-2012, 09:54
Nessun suggerimento?
Servono informazioni in più?