Gniazda, komunikacja pod linuxem

0

Witam wszystkich.

Mam taki problem z przesyłaniem danych a mianowicie jak klient podłączy się do serwera to serwer wysyła komunikat do klienta "Podlaczyles sie do serwera" i tak powinno byc ale po pobraniu danych od klienta "recv(gniazdo, buf, 250, 0)" serwer już nie che wysłać do klienta nic zawiesza sie wszystko dopóki nie wyłączę klienta.

Mam plik "serwer" taki :



#include "class.h"


#define MYPORT 5555 // port, z którym będą się łączyli użytkownicy
#define BACKLOG 10 


using namespace std;


// wyszukuja martwe  procesy
void sigchld_handler(int s)
    {
        while(wait(NULL) > 0);
    }
	
//######################################################

string IntToStr(int var) {
std::string s;
std::stringstream out;
out << var;
s = out.str();
return s;
}



 int main(){

	// Klasy
	CSQL sql;
	//Podziel podz;
	Exp exp; 
	 
 
	 int server, gniazdo,polecenie=0;
	 unsigned int dlugosc;
	 struct sockaddr_in moj_adres; //utworzenie struktury adres typu sockaddr_in
	 struct sockaddr_in adres_klienta;
	 socklen_t sin_size;
	 sin_size = sizeof(struct sockaddr_in);
	 int yes=1;
	 struct sigaction sa;
	 char *msg, *wynik;
	 char buf[250];
	 string dane,dane2;
	 vector<string> podzielone;
	 bool odebrano = false;
	 string query,imie,nazwisko;
	 char *pol;
	 MYSQL_RES* res;
	 MYSQL_ROW   row, end_row;
	 unsigned long *lengths; 
	 unsigned int num_fields;
	 
	 size_t wielkosc;
	 


	 moj_adres.sin_family = AF_INET; //adresy internetowe
	 moj_adres.sin_port = htons(MYPORT);
	 moj_adres.sin_addr.s_addr = INADDR_ANY; // przypisz do gniazda domyslny adres IP
	 memset(&(moj_adres.sin_zero), '\0', 8);
	 
 
 
 if ((server = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
	perror("BLAD funkcji socket !");
	exit(1);
 }

 if (setsockopt(server, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
	perror("BLAD funkcji setsockopt !");
	exit(1);
 }



 if (bind(server, (struct sockaddr *)&moj_adres, sizeof(struct sockaddr)) == -1) {
  perror("BLAD w dowiazaniu numeru portu do serwera !");
  exit(1);
 }
 
 
 if (listen(server, BACKLOG) == -1) {
  perror("BLAD podczas tworzenia kolejki połaczeń !");
  exit(1);
 }

 //zabiajmy martwe procesy
   sa.sa_handler = sigchld_handler; // zbierz martwe procesy
   sigemptyset(&sa.sa_mask);
   sa.sa_flags = SA_RESTART;
   if (sigaction(SIGCHLD, &sa, NULL) == -1) {
        perror("sigaction");
        exit(1);
    }
	
	
		
	printf("\033[01;34m Czekanie na polaczenie klienta \033[00m\n");
			// obslucha polaczoonych klientow
	
	

		
			 while(1) {  
				sin_size = sizeof(struct sockaddr_in);
				if ((gniazdo = accept(server, (struct sockaddr *)&adres_klienta, &sin_size)) == -1) {
						perror("accept");
						continue;
				}
				printf("\n\tNawiazano połaczenie z %s:%d\n",inet_ntoa(adres_klienta.sin_addr),ntohs(adres_klienta.sin_port));
				
				
				if(!fork()){
					//close(server); //zamykanie gniazda nasluchu
					msg = "\033[01;35m Podlaczyles sie do serwera \033[00m\n";
					if (send(gniazdo,msg , strlen(msg), 0) == -1) perror("send");
				}
				
				
				
				
				//####################################################################]
				//######### POBIERAMY DANE OD KLIENTA ########################################
					
					while(recv(gniazdo, buf, 250, 0) > 0)
						{
							dane.append(buf);
							odebrano = true; 
						}

					dane = dane.substr(0,1);// wycinanie z lancucha 1 znaków
					
					
					
					if(odebrano){
					if(dane == "p") polecenie = 2;
					if(dane == "z") polecenie = 1;
						 cout << "\n\n\t\t "<<dane << "\n\n\n\t\t "<<polecenie<< "\n\n\n\t\t "; 
						switch(polecenie){
							case 1:
										
								// laczenie z baza danych
								sql.Connect("localhost", "test", "test", "test",3306);
									
									exp.Split(dane," ", podzielone);
										
										wielkosc =podzielone.size();
										cout << "\n wielkosc wektora : " << wielkosc;

										for(size_t i = 0; i < podzielone.size()-1; i++) {
											imie = podzielone.at(i);
											i++;
											nazwisko =podzielone.at(i);	
											cout << "\n " << imie << " " << nazwisko ;
											query = "INSERT INTO `cpp` VALUES ( NULL , '"+imie+"', '"+nazwisko+"')";
											sql.Query(query); // zapisywanie do bazy danych
											//cout << "\n Zaptanie " << query;
										}
								dane.clear();
								podzielone.clear();
								sql.zamkni_mysql();//Zamykamy polaczenie z mysql
							break;
							case 2:
							
								// laczenie z baza danych
								sql.Connect("localhost", "test", "test", "test",3306);
								query = "SELECT * FROM `cpp`";
								res=sql.Query(query); // zapisywanie do bazy danych
								
								
								  if (res) 
								  {
									 
									 num_fields = mysql_num_fields(res); // liczba pol w wersie; 
									 while ( (row = mysql_fetch_row(res)) )
									 {
										lengths = mysql_fetch_lengths(res);
										// odbieranie 
										for(int i = 0; i < num_fields; i++)
										{
										   //printf("[%.*s] ", (int) lengths[i], row[i] ? row[i] : "NULL");// wyswietla nr oraz zawartosc 
										   dane2 += row[i]; 
										   dane2 += " ";
										}
										dane2 += "\n";
										//printf("\n");
									}
									
									//wysylanie do klienta	
//######################################################################
//TEGO JUZ NIE WYSYLA I TU MAM PROBLEM ALE NIE WIM CZY TO WINA SERWERA CZY KLIENTA

									if(!fork()){
										//close(server); //zamykanie gniazda nasluchu
										if (send(gniazdo,dane2.c_str() , strlen(dane2.c_str()), 0) == -1) perror("send");
										//close(gniazdo);
									}
//#####################################################################
									
								}
						sql.zamkni_mysql();//Zamykamy polaczenie z mysql
					}
				odebrano = false;
				
								
				}	
				
			}
		
 
 return 0;
 }

i Klienta :


   #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <errno.h>
    #include <string.h>
    #include <netdb.h>
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <sys/socket.h>
    #include <iostream>
    #include <fstream>
    #include <vector>

	using namespace std; 
	typedef vector<string> string_vector_type;
    #define PORT 5555 // port, z którym klient będzie się łączył
    #define MAXDATASIZE 100 // maksymalna ilość dancyh, jaką możemy otrzymać na raz
	
	// Funkcja do rozdzielania
	//###################################################################################
	void Split(const string& text, const string& separators, string_vector_type &words) {
		
    size_t n     = text.length ();
    size_t start = text.find_first_not_of (separators);

    while (start < n) {
        size_t stop = text.find_first_of (separators, start);
        if (stop > n) stop = n;
        words.push_back (text.substr (start, stop-start));
        start = text.find_first_not_of (separators, stop+1);
    }
	}
	
	// Funkcja do laczenia
	//############################################################
	// ######### COS JAKI IMPLODE W PHP #################################
	string implode( const string &glue, string_vector_type &pieces )
	{
    string a;
    int leng=pieces.size();
		for(int i=0; i<leng; i++)
		{
			a+= pieces[i];
			if (  i < (leng-1) )
				a+= glue;
			}
		return a;
	}
	//####################################################################
	
    int main(int argc, char *argv[])
    {
        int gniazdo, numbytes; 
        char buf[250];
		string dane;
        struct hostent *he;
        struct sockaddr_in adres_klienta; // informacja o adresie osoby łączącej się
		fstream plik; //wysyłany plik
		//char danezpliku; //nazwa pliku do wysłania
		int ile,i; //ilosc znaków w pliku do wysłania
		int len, bytes_sent;
		string_vector_type lines;
		char *linia; 
		
		printf("\n\t+------------------------------------------------+");
		printf("\n\t Client ver.0.1");
		printf("\n\t");
		printf("\n\t Autor: XXXXXXX");
		printf("\n\t+------------------------------------------------+\n\n");
		
        if (argc != 3) {
            fprintf(stderr,"Uzyj: klient hostname p  lub  klient hostname z\n");
            exit(1);
        }

        if ((he=gethostbyname(argv[1])) == NULL) {  // pobierz informacje o hoście
            perror("gethostbyname");
            exit(1);
        }
		
		
	

        if ((gniazdo = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
            perror("socket");
            exit(1);
        }

        adres_klienta.sin_family = AF_INET;    // host byte order
        adres_klienta.sin_port = htons(PORT);  // short, network byte order
        adres_klienta.sin_addr = *((struct in_addr *)he->h_addr);
        memset(&(adres_klienta.sin_zero), '\0', 8);  // wyzeruj resztę struktury
		
			
        if (connect(gniazdo, (struct sockaddr *)&adres_klienta,
                                              sizeof(struct sockaddr)) == -1) {
            perror("connect");
            exit(1);
        } else printf("%s\n", "Połączono...");
		
		
		printf("%s", "\nWysyłanie danych do servera.");
		

		dane = argv[2];
		dane += "\0";
		
		
		cout <<" \nDane z pliku:\n"<< dane <<endl;
		
		
		// Wysylanie danych do serwera
		if (send(gniazdo,dane.c_str() , strlen(dane.c_str()), 0) == -1) perror("send");
		
	//##############################################
	// POBIERANIE KOMUNIKATU O POLACZENIU 	
	if ((numbytes=recv(gniazdo, buf, 250, 0)) == -1) {
            perror("recv");
            exit(1);
        } else 	{
					buf[numbytes] = '\0';
					printf("Komunikat: %s",buf); 
				}


//##############################################
// ODBIERANIE LISTY NAZWISK 
	if ((numbytes=recv(gniazdo, buf, 250, 0)) == -1) {
            perror("recv");
            exit(1);
        } else 	{
					buf[numbytes] = '\0';
					printf("Komunikat: %s",buf); 
				}


				
        close(gniazdo);

        return 0;
    } 

</cpp>
0
while(recv(gniazdo, buf, 250, 0) > 0)
{
    ...
}

Przy takiej konstrukcji to się nie dziw, że się wiesza, bo pętla zostanie przerwana dopiero wtedy, gdy recv zwróci 0 (przerwane połączenie) lub SOCKET_ERROR.

dane += "\0"; //<--- po co to, przecież string z automatu dodaje '\0' na koniec? zresztą w tej formie to i tak nic nie da :)

if (send(gniazdo,
            dane.c_str() , 
            strlen(dane.c_str()), //<--- no z tym to pojechałeś ;) string ma metodę 'size'.
            0) == -1) perror("send");

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