recvfrom() - jak przerwać?

0

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;
}

0

Zrobic 2 watki, pierwszy bedzie uruchamial drugi i czekal na jego zakonczenie z timeoutem ( Event i WaitForSingleObject ), drugi natomiast bedzie odpalal recvfrom(); W przypadku kiedy pierwszy watek dostanie timeout z drugiego, powienien on 'uwalic' (Terminate, delete) drugi watek, w ten sposob masz przerwane dzialanie recvfrom();

0

Dzięki już działa. [green]

1 użytkowników online, w tym zalogowanych: 0, gości: 1