WItam, mam pytanie jak można przerwać wykonywanie funkcji recvfrom? Napisałem program klienta i serwera. Jak serwer działa to wszystko jest ok, ale jak wyłącze serwer to program się "zacina", a chodzi mi o to żeby po paru sekundach program klienta wyświetlił komunikat że nie odebrano odpowiedzi. Próbowałem to zrobić na wątkach ale coś mi nie działa. Podobno można do tego użyć funkcji signal() ale nie wiem jak jej użyć.
Serwer.c
#include <sys/socket.h>
#include <netinet/ip.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#define PORT 4033
#define BUF_SIZE 255
int sd, rc, res;
FILE *fp;
char buf[BUF_SIZE], host[20];
struct sockaddr_in addr;
struct sockaddr_in from;
void odbierz_datagram();
void wyslij_datagram();
main(int argv, char *args[]) {
strcpy(host, args[0]);
// gniazdo ...
sd = socket(PF_INET, SOCK_DGRAM, 0);
if (sd<0) {
fprintf(stderr, "%s\n", strerror(errno));
exit(EXIT_FAILURE);
}
// przypisanie adresu ...
addr.sin_family=PF_INET;
addr.sin_port=htons(PORT);
// host to network short (porzadek bajtow) ... sa tez dla long i odwrotne ...
addr.sin_addr.s_addr=INADDR_ANY;
res=bind(sd, (struct sockaddr *) &addr, sizeof(struct sockaddr_in));
// odbior danych ...
for(;;)
{ printf("-------------------------------------------------------------------------\n");
odbierz_datagram();
//if(fork()==0)
//{
fp=popen(buf, "r");
memset(buf, 0x0, BUF_SIZE);
long lSize = ftell (fp);
fread (buf, 1, lSize, fp);
pclose(fp);
printf("Wynik: \n %s", buf);
wyslij_datagram(buf);
//}else
//printf("blad forka");
}
// zamkniecie gniazda
close(sd);
}
void odbierz_datagram()
{
char msg[BUF_SIZE];
memset(msg, 0x0, BUF_SIZE);
memset(buf, 0x0, BUF_SIZE);
socklen_t fromlen = sizeof(from);
rc = recvfrom(sd, msg, BUF_SIZE, 0, (struct sockaddr *) &from, &fromlen);
if(rc<0)
fprintf(stderr, "%s\n", strerror(errno));
else
{
printf("%s> odebrano datagram: '%s' (%d)\n", host, msg, strlen(msg));
strcpy(buf, msg);
}
char tmp[2] = "RC";
if(!(strncmp(tmp, msg, 2)==0))//datagram nie jest potwierdzeniem
wyslij_datagram("RC");
}
void wyslij_datagram(char msg[BUF_SIZE])
{
rc = sendto(sd, msg, strlen(msg), 0, (struct sockaddr *) &from, sizeof(struct sockaddr_in));
if(rc<0)
printf("%s> nie mozna wyslac danych\n", host);
else
printf("%s> wyslano datagram: %s \n", host, msg);
char tmp[2] = "RC";
if(!(strncmp(tmp, msg, 2)==0))//datagram nie jest potwierdzeniem
odbierz_datagram();//przerobic na odbierz_potwierdzenie()
}
Klient.c
#include <sys/socket.h>
#include <netinet/ip.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#define BUF_SIZE 255
#define PORT 4033
int sd, rc, odpowiedz = 0;
char buf[BUF_SIZE], host[20];
char dane[BUF_SIZE];
struct sockaddr_in to;
void wyslij_datagram();
void odbierz_datagram();
void odbierz_potwierdzenie();
void sprawdz_odp();
main(int argv, char *args[]) {
if(argv<2)
{
printf("Wpisz: %s <serwer>\n", args[0]);
exit(1);
}
strcpy(host, args[0]);
// gniazdo ...
sd = socket(PF_INET, SOCK_DGRAM, 0);
if (sd<0) {
fprintf(stderr, "%s\n", strerror(errno));
exit(EXIT_FAILURE);
}
// wysylanie danych
to.sin_family=PF_INET;
to.sin_port=htons(PORT);
inet_aton(args[1], &to.sin_addr);
//program wlasciwy
memset(dane, 0x0, BUF_SIZE);
//printf("%s> ", args[0]);
//fputs("podaj ciag znakow: ", stdout);
//fgets(dane, sizeof(dane), stdin);
// if (!strncmp(dane, "exit", 4))
//return 1;
strcpy(dane, args[2]);
//dane[strlen(dane)-1]=0; //usuwam znak przejscia do noewj lini
wyslij_datagram(dane);
//odbierz_datagram();
// zamkniecie gniazda
close(sd);
}
void wyslij_datagram(char msg[BUF_SIZE])
{
rc = sendto(sd, msg, strlen(msg), 0, (struct sockaddr *) &to, sizeof(struct sockaddr_in));
if(rc<0)
printf("%s> nie mozna wyslac danych\n", host);
else
printf("%s> wyslano datagram: %s \n", host, msg);
//oczekiwanie na potwierdzenie
char tmp[2] = "RC";
if(!(strncmp(tmp, msg, 2)==0))//datagram nie jest potwierdzeniem
{
odbierz_potwierdzenie();//przerobic na odbierz_potwierdzenie()
odbierz_datagram();
}
}
void odbierz_datagram()
{
char msg[BUF_SIZE];
memset(msg, 0x0, BUF_SIZE);
memset(buf, 0x0, BUF_SIZE);
socklen_t tolen = sizeof(to);
printf("Odbierz datagram");
rc = recvfrom(sd, msg, BUF_SIZE, 0, (struct sockaddr *) &to, &tolen);
if(rc<0)
fprintf(stderr, "%s\n", strerror(errno));
else
{
printf("%s> odebrano datagram: \n %s\n ", host, msg);
strcpy(buf, msg);
}
char tmp[2] = "RC";
if(!(strncmp(tmp, msg, 2)==0))//datagram nie jest potwierdzeniem
wyslij_datagram("RC");
}
void odbierz_potwierdzenie()
{ int i;
pthread_t watek;
pthread_create( &watek, 0, sprawdz_odp, NULL);
for(i=0;i<3;i++)
{
if(odpowiedz == 1)
break;
//printf("FOR %d", i);
sleep(1);
}
if(!odpowiedz)
printf("%s> nie odebrano potwierdzenia", host);
//pthread_exit(watek);
}
void sprawdz_odp(){
memset(buf, 0x0, BUF_SIZE);
socklen_t tolen = sizeof(to);
printf("Dziala watek\n");
recvfrom(sd, buf, BUF_SIZE, 0,(struct sockaddr *) &to, &tolen);
printf("%s> odebrano potwierdzenie: %s\n", host, buf);
odpowiedz = 1;
}