client server linux uzycie watkow i selecta

0

Pisze server ktory ma za zadanie obsluzyc wielu klientow, do tego zadania uzywam watkow. Kazdy client na innym watku, pozniej w celu sprawdzenia
czy nadeszla jakas nowa informacja na poszczegolny watek chce uzyc selekta aby obejs sytuacje kiedy czekanie na otrzymywanie danych bedzie mi blokowalo
dany watek i wywolanie ctr + c w takiej sytuacji nie zadziala az do nadejscia jakiejs wiadomosc; oto kod servera:

http://pastebin.com/8gCsC7d9

a tutaj client:

http://pastebin.com/iTFUUPEL

po wcisnieciu ctr +c po stronie servera server powinien zamknac wszystkie watki i samego siebie. Problem polega na tym ,ze program nie dziala prawidlowo
i po wcisnieciu ctrl+c program tworzy jakis dodatkowy watek oraz nie konczy programu glownego i nie jestem pewny czy zamyka poprawnie pozostałe watki
mogłby ktos mi z tym pomoc i jak cos wyjasnic co musze poprawic?

1

Niezły burdel w kodzie :- ).

Z tego co widzę, ma to być chat, tak?
Do chata nie jest Ci potrzebna multipleksacja I/O selectem. Wystarczy że po accepcie zrobisz tak:
1.do tablicy zapiszesz deskryptor gniazda nowego klienta.
2.puscisz wątek nowego klienta.
3.jeśli klient otrzymał wiadomość to rozsyła ją do wszystkich gniazd w tablicy, jeśli sie rozłączył to z wątku klienta usuwasz jego deskryptor z tablicy
I wszystko :- )

Co co ctrl+c to źle kombinujesz, wystarczy wywołać exit, przy wywołaniu exit sprzątaniem, czyli zamknięciem gniazd itp, zajmuje sie kernel, więc ten bool tam niepotrzebny, ew. dla pewności możesz ustawić sobie callbacki na std::atexit i tam wszystko posprzątać.

Co do kodu, to (pomijając reszte)
Po kiego grzyba Ci te 2 while?
to while((new_connect=accept(my_socket_server, (struct sockaddr*)&server_addr,&laddr_len))==0); wykona się w przypadku pomyślnego połączenia tylko raz, i w przypadku błędu, również tylko raz. Bez sensu.

Co do wątków to zostaw pthread a użyj <thread> z c++11, oszczędzisz sobie wiele kłopotów.

I jak testujesz taki np.chat i nie ma konieczności pisania własnego klienta, to testuj za pomocą telnetu, bo być może twój klient też jest lipny.

Masz tu przykład.

#include <iostream>
#include <string.h>
#include <netinet/in.h>
#include <algorithm>
#include <sys/socket.h>
#include <thread>
/** usage, telnet localhost 8888 **/
std::vector<int> clients;
void connection_handler(int);
int main()
{
	sockaddr_in servaddr;
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(8888);
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	int yes = 1;
	
	int listen_socket = socket(AF_INET, SOCK_STREAM, 0);
	setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
	bind(listen_socket, (sockaddr*)&servaddr, sizeof(servaddr));
	listen(listen_socket, 10);
	
	int newfd = 0;
	while((newfd = accept(listen_socket, nullptr, nullptr)) > 0)
	{
		clients.push_back(newfd);
		std::thread client_thread(connection_handler, newfd) ;
		client_thread.detach();
	}
	
}
void connection_handler(int client)
{
	int rcv_bytes = 0, snd_bytes = 0;
	std::array<char, 250> buff = {0};
	while((rcv_bytes = recv(client, buff.data(), buff.size(), 0)) > 0)
	{
		for(auto cli : clients){
			if(cli != client)
				send(cli, buff.data(), strlen(buff.data()), 0);
		}
		memset(buff.data(), 0, buff.size());
	}
	clients.erase(std::find(clients.begin(), clients.end(), client));
	std::cout << client << " drop..\n";
}

 
0

Dzięki wielkie za pomoc, hmm no to do tego while'a to fakt ze niepotrzebnie w ogole to tam bylo :) a co do rozwiazanie porblemu to dzieki za kod:) ale ja musze to
rozwiazać w ten sposob i poprawic ten kod niestety :( ale z Twoim na bank sie zapoznam i w sumie dzieki za podrzucenie pomyslu zeby zglebic sie w nowym standardzie mysle ze to dobre ukierunkowanie :).

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