Program sieciowy - równoległy

0

Witam, napisałem kawałek serwera TCP/IP ale niestety nie działa w sposób równoległy.
chodzi mi żeby wielu klientów mogło naraz wykonywać operacje.

#include "potnaz.h"
#include "d.h"

using namespace std;

void start(int pid); //start serwera TCP/IP
void stop(); // koniec serwera TCP/IP

int main(int arg, char **argv)
{
unsigned int port = 6666;                                        /*port serwera*/
struct sockaddr_in serwer_adres;                                 /*adres serwera*/
struct sockaddr_in klient_adres;                                 /*adres serwera*/		
unsigned int sockfd, newsockfd;
unsigned int klient;
char recv_client_msg[100];
long odebraneGniazdo;
char tab[111];
int pid;

//opcje wlanczania serwera
if ( arg < 2) 
{
 cout << "Za mala liczba argumentow" << endl; 
 exit(0);
}

if ((strcmp(argv[1],"stop") != 0) && (strcmp(argv[1],"start")!=0 ))
{
	cout << "Nie znane polecenie" << endl;
	cout << "Znam tylko start/stop" << endl; 
	exit(0);

}

                                                             

if (strcmp(argv[1],"stop") == 0 ) 
{ 
	stop();
}

if (strcmp(argv[1],"start") == 0 ) 
{ 
	start(0);
}  
//koniec opcji wlanczania serwera


	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) 
	{		
	    printf("blad socket()");
	    return 1;
	}
	//dowiazanie adesu lokalnego by umozliwic wysylanie klientowi pakietu do nas
	bzero((char *)&serwer_adres, sizeof(serwer_adres));
	serwer_adres.sin_family = AF_INET;
        serwer_adres.sin_port = ntohs(port);
        serwer_adres.sin_addr.s_addr = htonl(INADDR_ANY);

    /*wiazanie adresu z gniazdem*/
    if (bind(sockfd, (struct sockaddr *) &serwer_adres, sizeof(serwer_adres)) == -1) 
    {
    	printf("blad bind()\n");
    	return 1;
    }
    
    do
    {
    	listen(sockfd, 1);
    	klient = sizeof(klient_adres);
    	newsockfd = accept(sockfd, (struct sockaddr *) &klient_adres, &klient );
    	if(newsockfd == -1) 
    	{
    		printf("blad accept()");
    		return 1; 
    	}
    	//tworzenie procesu potomnego
    	if((pid = fork()) == -1)
    	{
    		perror("nie udalo sie utworzyc procesu potomnego ");
    	}
    	else if(pid == 0)
    	{
    		read(newsockfd ,recv_client_msg, 100);
    		odebraneGniazdo = atol(recv_client_msg);
    		cout << "odebrana liczba to " << odebraneGniazdo << endl;
    		sleep(20);
    		odebraneGniazdo *= odebraneGniazdo; 
    		cout << "wysylam liczbe " << odebraneGniazdo << endl;
    		sprintf(tab, "%ld", odebraneGniazdo);
    		write(newsockfd ,tab, (strlen(tab)+1));
    		//close(newsockfd);
    	}
    	else
    	{
    		wait(0);
    		close(newsockfd);
    	}
    }while(1);                                               
//koniec funkcji int main    
}



void start(int pid)
{
void *pw;
static int shmid;

	if(pid != 0)
	{
		if ( (pw=shmat(shmid,0,0)) == (char*)-1) perror("Nie udestepniono segmentu"); 
		cout << "pid = " << pid << endl;
		bcopy(&pid, pw, sizeof(pid));
		shmdt(pw);
		return;
	}
	//tworzenie pamieci wspolnej
	if((shmid=shmget(kluczd,sizeof(pid), IPC_CREAT|IPC_EXCL|prawa)) < 0 )
	{ 	
		perror("serwer juz dziala");	 
		exit(1);
	}		

}

void stop()
{
int pid;
void *pw;
int shmid;

	if ( (shmid=shmget(kluczd,0, prawa)) != -1)  
	{ 
		//perror("Serwer jest wylaczony ");
		if ( (pw=shmat(shmid,0,0)) == (char*)-1) perror("Nie udestepniono segmentu");
		bcopy(pw, &pid, sizeof(pid));
		shmdt(pw);
		shmctl(shmid, IPC_RMID, NULL);
		kill (pid,SIGTERM);
		puts("serwer zatrzymany");
		exit(0);
		
	}
	else
	{
		puts("Brak serwera");
		exit(1);		
	}
		
}

Będę bardzo bardzo zobowiązany.

wstawienie sformatowanej wersji kodu z linku podanego w komentarzu do poniższego postu - fp

0

Pocztaj o multi {io/threading/processing}, ew. sformatuj kod, zeby przecietny czlowiek mogl go przeczytac.

Edit: ofc jeszcze ASIO jest ;d

0

Dodaj wątki do swojego programu, tj każdy klient to osobny wątek, aby serwer mógł je obsługiwać jednocześnie

0

właśnie nie mogę użyć wątków w tym zadaniu. :(

Właśnie utworzyłem proces potomny który dziedziczy nr socketu klienta.
a a nie wiem czemu jak usune wait(0); to program się zapętla :( a nie powinien , tylko powinien się zawiesic na nadsłuchiwaniu na porcie.

0

Musisz zaimplementować wielowątkowość dla socketów, a dokładniej każde połączenie zapisać w tablicy jako wątek.

0

Wywołaj listen (raz) przed wejściem do pętli z accept.

0
/*wiazanie adresu z gniazdem*/
    if (bind(sockfd, (struct sockaddr *) &serwer_adres, sizeof(serwer_adres)) == -1) 
    {
    	printf("blad bind()\n");
    	return 1;
    }
    listen(sockfd, 1);
    do
    {
    	
    	klient = sizeof(klient_adres);
    	newsockfd = accept(sockfd, (struct sockaddr *) &klient_adres, &klient );
....

zrobiłem i dalej to samo

dodanie znacznika <code class="cpp"> - fp

0

Wywal to bezsensowne wait(0), a w procesie potomny na początku dodaj close(sockfd).

0

Ale jak? Jak jeden jest połączony to nikt inny się nie połączy do niego, dopiero jak ten poprzedni zejdzie z połączenie ta może kolejny wejść i nadawać...

0

Dzięki wielki jesteś. Program działa prawie bez błędnie, tylko jak serwer dostaje liczbę to wyrzuca błąd "blad accept()" ale bez problemu wysyła i odbiera dane.

P.S. można prosić o małe wytłumaczenie dlaczego listen() jest przed pętla ??

0

W dosc sporym uproszczeniu zamienia gniazdo na gniazdo nasluchujace.

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